prjct-cli 0.4.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 (71) hide show
  1. package/CHANGELOG.md +312 -0
  2. package/CLAUDE.md +300 -0
  3. package/LICENSE +21 -0
  4. package/README.md +424 -0
  5. package/bin/prjct +214 -0
  6. package/core/agent-detector.js +249 -0
  7. package/core/agents/claude-agent.js +250 -0
  8. package/core/agents/codex-agent.js +256 -0
  9. package/core/agents/terminal-agent.js +465 -0
  10. package/core/analyzer.js +596 -0
  11. package/core/animations-simple.js +240 -0
  12. package/core/animations.js +277 -0
  13. package/core/author-detector.js +218 -0
  14. package/core/capability-installer.js +190 -0
  15. package/core/command-installer.js +775 -0
  16. package/core/commands.js +2050 -0
  17. package/core/config-manager.js +335 -0
  18. package/core/migrator.js +784 -0
  19. package/core/path-manager.js +324 -0
  20. package/core/project-capabilities.js +144 -0
  21. package/core/session-manager.js +439 -0
  22. package/core/version.js +107 -0
  23. package/core/workflow-engine.js +213 -0
  24. package/core/workflow-prompts.js +192 -0
  25. package/core/workflow-rules.js +147 -0
  26. package/package.json +80 -0
  27. package/scripts/install.sh +433 -0
  28. package/scripts/verify-installation.sh +158 -0
  29. package/templates/agents/AGENTS.md +164 -0
  30. package/templates/commands/analyze.md +125 -0
  31. package/templates/commands/cleanup.md +102 -0
  32. package/templates/commands/context.md +105 -0
  33. package/templates/commands/design.md +113 -0
  34. package/templates/commands/done.md +44 -0
  35. package/templates/commands/fix.md +87 -0
  36. package/templates/commands/git.md +79 -0
  37. package/templates/commands/help.md +72 -0
  38. package/templates/commands/idea.md +50 -0
  39. package/templates/commands/init.md +237 -0
  40. package/templates/commands/next.md +74 -0
  41. package/templates/commands/now.md +35 -0
  42. package/templates/commands/progress.md +92 -0
  43. package/templates/commands/recap.md +86 -0
  44. package/templates/commands/roadmap.md +107 -0
  45. package/templates/commands/ship.md +41 -0
  46. package/templates/commands/stuck.md +48 -0
  47. package/templates/commands/task.md +97 -0
  48. package/templates/commands/test.md +94 -0
  49. package/templates/commands/workflow.md +224 -0
  50. package/templates/examples/natural-language-examples.md +320 -0
  51. package/templates/mcp-config.json +8 -0
  52. package/templates/workflows/analyze.md +159 -0
  53. package/templates/workflows/cleanup.md +73 -0
  54. package/templates/workflows/context.md +72 -0
  55. package/templates/workflows/design.md +88 -0
  56. package/templates/workflows/done.md +20 -0
  57. package/templates/workflows/fix.md +201 -0
  58. package/templates/workflows/git.md +192 -0
  59. package/templates/workflows/help.md +13 -0
  60. package/templates/workflows/idea.md +22 -0
  61. package/templates/workflows/init.md +80 -0
  62. package/templates/workflows/natural-language-handler.md +183 -0
  63. package/templates/workflows/next.md +44 -0
  64. package/templates/workflows/now.md +19 -0
  65. package/templates/workflows/progress.md +113 -0
  66. package/templates/workflows/recap.md +66 -0
  67. package/templates/workflows/roadmap.md +95 -0
  68. package/templates/workflows/ship.md +18 -0
  69. package/templates/workflows/stuck.md +25 -0
  70. package/templates/workflows/task.md +109 -0
  71. package/templates/workflows/test.md +243 -0
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Simple animations with basic colors for better compatibility
3
+ * Fallback when terminal doesn't support RGB colors
4
+ */
5
+
6
+ const chalk = require('chalk')
7
+
8
+ const colors = {
9
+ success: chalk.green,
10
+ error: chalk.red,
11
+ warning: chalk.yellow,
12
+ info: chalk.blue,
13
+ ship: chalk.cyan,
14
+ celebrate: chalk.magenta,
15
+ focus: chalk.green.bold,
16
+ idea: chalk.yellow,
17
+ progress: chalk.blue,
18
+ task: chalk.cyan,
19
+ primary: chalk.magenta,
20
+ secondary: chalk.cyan,
21
+ text: chalk.white,
22
+ subtext: chalk.gray,
23
+ dim: chalk.gray,
24
+ }
25
+
26
+ const frames = {
27
+ rocket: [
28
+ ' ๐Ÿš€ ',
29
+ ' ๐Ÿš€ ',
30
+ ' ๐Ÿš€ ',
31
+ ' ๐Ÿš€ ',
32
+ ' ๐Ÿš€ ',
33
+ '๐Ÿš€ ',
34
+ ],
35
+ sparkles: [
36
+ 'โœจ ๏ฝฅ ๏ฝก๏พŸโ˜†: *.โ˜ฝ .* :โ˜†๏พŸ. โœจ',
37
+ '๏ฝฅ ๏ฝก๏พŸโ˜†: *.โ˜ฝ .* :โ˜†๏พŸ. โœจ ๏ฝฅ',
38
+ '๏ฝก๏พŸโ˜†: *.โ˜ฝ .* :โ˜†๏พŸ. โœจ ๏ฝฅ ๏ฝก๏พŸ',
39
+ 'โ˜†: *.โ˜ฝ .* :โ˜†๏พŸ. โœจ ๏ฝฅ ๏ฝก๏พŸโ˜†:',
40
+ ],
41
+ loading: [
42
+ 'โ ‹',
43
+ 'โ ™',
44
+ 'โ น',
45
+ 'โ ธ',
46
+ 'โ ผ',
47
+ 'โ ด',
48
+ 'โ ฆ',
49
+ 'โ ง',
50
+ 'โ ‡',
51
+ 'โ ',
52
+ ],
53
+ progress: [
54
+ '[ ]',
55
+ '[โ–“ ]',
56
+ '[โ–“โ–“ ]',
57
+ '[โ–“โ–“โ–“ ]',
58
+ '[โ–“โ–“โ–“โ–“ ]',
59
+ '[โ–“โ–“โ–“โ–“โ–“ ]',
60
+ '[โ–“โ–“โ–“โ–“โ–“โ–“ ]',
61
+ '[โ–“โ–“โ–“โ–“โ–“โ–“โ–“ ]',
62
+ '[โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“ ]',
63
+ '[โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“ ]',
64
+ '[โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“]',
65
+ ],
66
+ celebration: [
67
+ '๐ŸŽ‰',
68
+ '๐ŸŽŠ',
69
+ 'โœจ',
70
+ '๐ŸŒŸ',
71
+ 'โญ',
72
+ '๐Ÿ’ซ',
73
+ '๐ŸŽ†',
74
+ '๐ŸŽ‡',
75
+ ],
76
+ }
77
+
78
+ const banners = {
79
+ ship: `
80
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
81
+ โ•‘ ๐Ÿš€ ${colors.ship.bold('S H I P P E D !')} ๐Ÿš€ โ•‘
82
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`,
83
+
84
+ success: `
85
+ โœจ ${colors.success.bold('Success!')} โœจ`,
86
+
87
+ error: `
88
+ โŒ ${colors.error.bold('Error')} โŒ`,
89
+
90
+ welcome: `
91
+ ${colors.primary('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—')}
92
+ ${colors.primary('โ•‘')} ${colors.text.bold('๐Ÿš€ prjct')}${colors.primary('/')}${colors.secondary.bold('cli')} ${colors.primary('โ•‘')}
93
+ ${colors.primary('โ•‘')} ${colors.dim('Ship faster with zero friction')} ${colors.primary('โ•‘')}
94
+ ${colors.primary('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•')}`,
95
+
96
+ cleanup: `
97
+ ${colors.focus('๐Ÿงน โœจ Cleanup Magic โœจ ๐Ÿงน')}`,
98
+
99
+ focus: `
100
+ ${colors.focus('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”')}
101
+ ${colors.focus.bold(' ๐ŸŽฏ FOCUS MODE ๐ŸŽฏ ')}
102
+ ${colors.focus('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”')}`,
103
+ }
104
+
105
+ async function animate(frames, duration = 100) {
106
+ for (const frame of frames) {
107
+ process.stdout.write('\r' + frame)
108
+ await sleep(duration)
109
+ }
110
+ process.stdout.write('\r' + ' '.repeat(30) + '\r')
111
+ }
112
+
113
+ async function typeWriter(text, delay = 30) {
114
+ for (let i = 0; i <= text.length; i++) {
115
+ process.stdout.write('\r' + text.slice(0, i) + (i < text.length ? 'โ–‹' : ''))
116
+ await sleep(delay)
117
+ }
118
+ process.stdout.write('\n')
119
+ }
120
+
121
+ async function progressBar(duration = 1000, label = 'Processing') {
122
+ const steps = 20
123
+ const stepDuration = duration / steps
124
+
125
+ for (let i = 0; i <= steps; i++) {
126
+ const percent = Math.round((i / steps) * 100)
127
+ const filled = 'โ–“'.repeat(i)
128
+ const empty = 'โ–‘'.repeat(steps - i)
129
+ const bar = `${colors.dim(label)} [${colors.primary(filled)}${colors.dim(empty)}] ${colors.text(percent + '%')}`
130
+ process.stdout.write('\r' + bar)
131
+ await sleep(stepDuration)
132
+ }
133
+ process.stdout.write('\n')
134
+ }
135
+
136
+ async function sparkle(message) {
137
+ const sparkles = ['โœจ', 'โญ', '๐Ÿ’ซ', '๐ŸŒŸ']
138
+ let output = ''
139
+
140
+ for (let i = 0; i < 3; i++) {
141
+ const spark = sparkles[Math.floor(Math.random() * sparkles.length)]
142
+ output = `${spark} ${message} ${spark}`
143
+ process.stdout.write('\r' + output)
144
+ await sleep(200)
145
+ process.stdout.write('\r' + ' '.repeat(output.length))
146
+ await sleep(100)
147
+ }
148
+
149
+ console.log(output)
150
+ }
151
+
152
+ function sleep(ms) {
153
+ return new Promise(resolve => setTimeout(resolve, ms))
154
+ }
155
+
156
+ function formatShip(feature, count) {
157
+ const banner = banners.ship
158
+ const stats = `
159
+ ${colors.text('Feature:')} ${colors.ship.bold(feature)}
160
+ ${colors.text('Total shipped:')} ${colors.success.bold(count)}
161
+ ${colors.text('Velocity:')} ${colors.celebrate('๐Ÿ”ฅ On fire!')}
162
+ `
163
+
164
+ return banner + stats
165
+ }
166
+
167
+ function formatFocus(task, timestamp) {
168
+ const banner = banners.focus
169
+ const info = `
170
+ ${colors.text('Current task:')} ${colors.focus.bold(task)}
171
+ ${colors.dim('Started:')} ${colors.subtext(timestamp)}
172
+ `
173
+
174
+ return banner + info
175
+ }
176
+
177
+ function formatSuccess(message) {
178
+ return `${colors.success('โœ…')} ${colors.text(message)}`
179
+ }
180
+
181
+ function formatError(message) {
182
+ return `${colors.error('โŒ')} ${colors.text(message)}`
183
+ }
184
+
185
+ function formatIdea(idea) {
186
+ return `
187
+ ${colors.idea('๐Ÿ’ก Idea captured!')}
188
+ ${colors.text('โ€•'.repeat(30))}
189
+ ${colors.subtext(idea)}
190
+ ${colors.text('โ€•'.repeat(30))}
191
+ ${colors.dim('Added to your ideas backlog')}
192
+ `
193
+ }
194
+
195
+ function formatCleanup(filesRemoved, tasksArchived, spaceFeed) {
196
+ return `
197
+ ${banners.cleanup}
198
+
199
+ ${colors.text('๐Ÿ—‘๏ธ Files removed:')} ${colors.success.bold(filesRemoved)}
200
+ ${colors.text('๐Ÿ“ฆ Tasks archived:')} ${colors.success.bold(tasksArchived)}
201
+ ${colors.text('๐Ÿ’พ Space freed:')} ${colors.success.bold(spaceFeed + ' MB')}
202
+
203
+ ${colors.celebrate('โœจ Your project is clean and lean!')}
204
+ `
205
+ }
206
+
207
+ function formatRecap(data) {
208
+ const divider = colors.primary('โ”'.repeat(40))
209
+
210
+ return `
211
+ ${divider}
212
+ ${colors.primary.bold('๐Ÿ“Š PROJECT RECAP')}
213
+ ${divider}
214
+
215
+ ${colors.text('๐ŸŽฏ Current focus:')} ${data.currentTask || colors.dim('No active task')}
216
+ ${colors.text('๐Ÿš€ Shipped this week:')} ${colors.success.bold(data.shippedCount)}
217
+ ${colors.text('๐Ÿ“ Queued tasks:')} ${colors.info.bold(data.queuedCount)}
218
+ ${colors.text('๐Ÿ’ก Ideas captured:')} ${colors.idea.bold(data.ideasCount)}
219
+
220
+ ${divider}
221
+ ${colors.dim('Keep shipping! ๐Ÿš€')}
222
+ `
223
+ }
224
+
225
+ module.exports = {
226
+ colors,
227
+ frames,
228
+ banners,
229
+ animate,
230
+ typeWriter,
231
+ progressBar,
232
+ sparkle,
233
+ formatShip,
234
+ formatFocus,
235
+ formatSuccess,
236
+ formatError,
237
+ formatIdea,
238
+ formatCleanup,
239
+ formatRecap,
240
+ }
@@ -0,0 +1,277 @@
1
+ /**
2
+ * Cool animations and visual effects for prjct
3
+ * Using Catppuccin color palette
4
+ */
5
+
6
+ const chalk = require('chalk')
7
+
8
+ if (!chalk.supportsColor) {
9
+ chalk.level = 3 // Full RGB color support
10
+ process.env.FORCE_COLOR = '3'
11
+ }
12
+
13
+ const catppuccin = {
14
+
15
+ rosewater: '#f5e0dc',
16
+ flamingo: '#f2cdcd',
17
+ pink: '#f5c2e7',
18
+ mauve: '#cba6f7',
19
+ red: '#f38ba8',
20
+ maroon: '#eba0ac',
21
+ peach: '#fab387',
22
+ yellow: '#f9e2af',
23
+ green: '#a6e3a1',
24
+ teal: '#94e2d5',
25
+ sky: '#89dceb',
26
+ sapphire: '#74c7ec',
27
+ blue: '#89b4fa',
28
+ lavender: '#b4befe',
29
+
30
+ text: '#cdd6f4',
31
+ subtext1: '#bac2de',
32
+ subtext0: '#a6adc8',
33
+ overlay2: '#9399b2',
34
+ overlay1: '#7f849c',
35
+ overlay0: '#6c7086',
36
+ surface2: '#585b70',
37
+ surface1: '#45475a',
38
+ surface0: '#313244',
39
+ base: '#1e1e2e',
40
+ mantle: '#181825',
41
+ crust: '#11111b',
42
+ }
43
+
44
+ const colors = {
45
+ success: chalk.hex(catppuccin.green),
46
+ error: chalk.hex(catppuccin.red),
47
+ warning: chalk.hex(catppuccin.yellow),
48
+ info: chalk.hex(catppuccin.blue),
49
+ ship: chalk.hex(catppuccin.sapphire),
50
+ celebrate: chalk.hex(catppuccin.pink),
51
+ focus: chalk.hex(catppuccin.teal),
52
+ idea: chalk.hex(catppuccin.yellow),
53
+ progress: chalk.hex(catppuccin.lavender),
54
+ task: chalk.hex(catppuccin.mauve),
55
+ primary: chalk.hex(catppuccin.mauve),
56
+ secondary: chalk.hex(catppuccin.sky),
57
+ text: chalk.hex(catppuccin.text),
58
+ subtext: chalk.hex(catppuccin.subtext1),
59
+ dim: chalk.hex(catppuccin.overlay1),
60
+ }
61
+
62
+ const frames = {
63
+ rocket: [
64
+ ' ๐Ÿš€ ',
65
+ ' ๐Ÿš€ ',
66
+ ' ๐Ÿš€ ',
67
+ ' ๐Ÿš€ ',
68
+ ' ๐Ÿš€ ',
69
+ '๐Ÿš€ ',
70
+ ],
71
+ sparkles: [
72
+ 'โœจ ๏ฝฅ ๏ฝก๏พŸโ˜†: *.โ˜ฝ .* :โ˜†๏พŸ. โœจ',
73
+ '๏ฝฅ ๏ฝก๏พŸโ˜†: *.โ˜ฝ .* :โ˜†๏พŸ. โœจ ๏ฝฅ',
74
+ '๏ฝก๏พŸโ˜†: *.โ˜ฝ .* :โ˜†๏พŸ. โœจ ๏ฝฅ ๏ฝก๏พŸ',
75
+ 'โ˜†: *.โ˜ฝ .* :โ˜†๏พŸ. โœจ ๏ฝฅ ๏ฝก๏พŸโ˜†:',
76
+ ],
77
+ loading: [
78
+ 'โ ‹',
79
+ 'โ ™',
80
+ 'โ น',
81
+ 'โ ธ',
82
+ 'โ ผ',
83
+ 'โ ด',
84
+ 'โ ฆ',
85
+ 'โ ง',
86
+ 'โ ‡',
87
+ 'โ ',
88
+ ],
89
+ progress: [
90
+ '[ ]',
91
+ '[โ–“ ]',
92
+ '[โ–“โ–“ ]',
93
+ '[โ–“โ–“โ–“ ]',
94
+ '[โ–“โ–“โ–“โ–“ ]',
95
+ '[โ–“โ–“โ–“โ–“โ–“ ]',
96
+ '[โ–“โ–“โ–“โ–“โ–“โ–“ ]',
97
+ '[โ–“โ–“โ–“โ–“โ–“โ–“โ–“ ]',
98
+ '[โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“ ]',
99
+ '[โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“ ]',
100
+ '[โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“โ–“]',
101
+ ],
102
+ celebration: [
103
+ '๐ŸŽ‰',
104
+ '๐ŸŽŠ',
105
+ 'โœจ',
106
+ '๐ŸŒŸ',
107
+ 'โญ',
108
+ '๐Ÿ’ซ',
109
+ '๐ŸŽ†',
110
+ '๐ŸŽ‡',
111
+ ],
112
+ }
113
+
114
+ const banners = {
115
+ ship: `
116
+ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
117
+ โ•‘ ๐Ÿš€ ${colors.ship.bold('S H I P P E D !')} ๐Ÿš€ โ•‘
118
+ โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`,
119
+
120
+ success: `
121
+ โœจ ${colors.success.bold('Success!')} โœจ`,
122
+
123
+ error: `
124
+ โŒ ${colors.error.bold('Error')} โŒ`,
125
+
126
+ welcome: `
127
+ ${colors.primary('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—')}
128
+ ${colors.primary('โ•‘')} ${colors.text.bold('๐Ÿš€ prjct')}${colors.primary('/')}${colors.secondary.bold('cli')} ${colors.primary('โ•‘')}
129
+ ${colors.primary('โ•‘')} ${colors.dim('Ship faster with zero friction')} ${colors.primary('โ•‘')}
130
+ ${colors.primary('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•')}`,
131
+
132
+ cleanup: `
133
+ ${colors.focus('๐Ÿงน โœจ Cleanup Magic โœจ ๐Ÿงน')}`,
134
+
135
+ focus: `
136
+ ${colors.focus('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”')}
137
+ ${colors.focus.bold(' ๐ŸŽฏ FOCUS MODE ๐ŸŽฏ ')}
138
+ ${colors.focus('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”')}`,
139
+ }
140
+
141
+ async function animate(frames, duration = 100) {
142
+ for (const frame of frames) {
143
+ process.stdout.write('\r' + frame)
144
+ await sleep(duration)
145
+ }
146
+ process.stdout.write('\r' + ' '.repeat(30) + '\r')
147
+ }
148
+
149
+ async function typeWriter(text, delay = 30) {
150
+ for (let i = 0; i <= text.length; i++) {
151
+ process.stdout.write('\r' + text.slice(0, i) + (i < text.length ? 'โ–‹' : ''))
152
+ await sleep(delay)
153
+ }
154
+ process.stdout.write('\n')
155
+ }
156
+
157
+ async function progressBar(duration = 1000, label = 'Processing') {
158
+ const steps = 20
159
+ const stepDuration = duration / steps
160
+
161
+ for (let i = 0; i <= steps; i++) {
162
+ const percent = Math.round((i / steps) * 100)
163
+ const filled = 'โ–“'.repeat(i)
164
+ const empty = 'โ–‘'.repeat(steps - i)
165
+ const bar = `${colors.dim(label)} [${colors.primary(filled)}${colors.dim(empty)}] ${colors.text(percent + '%')}`
166
+ process.stdout.write('\r' + bar)
167
+ await sleep(stepDuration)
168
+ }
169
+ process.stdout.write('\n')
170
+ }
171
+
172
+ async function sparkle(message) {
173
+ const sparkles = ['โœจ', 'โญ', '๐Ÿ’ซ', '๐ŸŒŸ']
174
+ let output = ''
175
+
176
+ for (let i = 0; i < 3; i++) {
177
+ const spark = sparkles[Math.floor(Math.random() * sparkles.length)]
178
+ output = `${spark} ${message} ${spark}`
179
+ process.stdout.write('\r' + output)
180
+ await sleep(200)
181
+ process.stdout.write('\r' + ' '.repeat(output.length))
182
+ await sleep(100)
183
+ }
184
+
185
+ console.log(output)
186
+ }
187
+
188
+ function sleep(ms) {
189
+ return new Promise(resolve => setTimeout(resolve, ms))
190
+ }
191
+
192
+ function formatShip(feature, count) {
193
+ const banner = banners.ship
194
+ const stats = `
195
+ ${colors.text('Feature:')} ${colors.ship.bold(feature)}
196
+ ${colors.text('Total shipped:')} ${colors.success.bold(count)}
197
+ ${colors.text('Velocity:')} ${colors.celebrate('๐Ÿ”ฅ On fire!')}
198
+ `
199
+
200
+ return banner + stats
201
+ }
202
+
203
+ function formatFocus(task, timestamp) {
204
+ const banner = banners.focus
205
+ const info = `
206
+ ${colors.text('Current task:')} ${colors.focus.bold(task)}
207
+ ${colors.dim('Started:')} ${colors.subtext(timestamp)}
208
+ `
209
+
210
+ return banner + info
211
+ }
212
+
213
+ function formatSuccess(message) {
214
+ return `${colors.success('โœ…')} ${colors.text(message)}`
215
+ }
216
+
217
+ function formatError(message) {
218
+ return `${colors.error('โŒ')} ${colors.text(message)}`
219
+ }
220
+
221
+ function formatIdea(idea) {
222
+ return `
223
+ ${colors.idea('๐Ÿ’ก Idea captured!')}
224
+ ${colors.text('โ€•'.repeat(30))}
225
+ ${colors.subtext(idea)}
226
+ ${colors.text('โ€•'.repeat(30))}
227
+ ${colors.dim('Added to your ideas backlog')}
228
+ `
229
+ }
230
+
231
+ function formatCleanup(filesRemoved, tasksArchived, spaceFeed) {
232
+ return `
233
+ ${banners.cleanup}
234
+
235
+ ${colors.text('๐Ÿ—‘๏ธ Files removed:')} ${colors.success.bold(filesRemoved)}
236
+ ${colors.text('๐Ÿ“ฆ Tasks archived:')} ${colors.success.bold(tasksArchived)}
237
+ ${colors.text('๐Ÿ’พ Space freed:')} ${colors.success.bold(spaceFeed + ' MB')}
238
+
239
+ ${colors.celebrate('โœจ Your project is clean and lean!')}
240
+ `
241
+ }
242
+
243
+ function formatRecap(data) {
244
+ const divider = colors.primary('โ”'.repeat(40))
245
+
246
+ return `
247
+ ${divider}
248
+ ${colors.primary.bold('๐Ÿ“Š PROJECT RECAP')}
249
+ ${divider}
250
+
251
+ ${colors.text('๐ŸŽฏ Current focus:')} ${data.currentTask || colors.dim('No active task')}
252
+ ${colors.text('๐Ÿš€ Shipped this week:')} ${colors.success.bold(data.shippedCount)}
253
+ ${colors.text('๐Ÿ“ Queued tasks:')} ${colors.info.bold(data.queuedCount)}
254
+ ${colors.text('๐Ÿ’ก Ideas captured:')} ${colors.idea.bold(data.ideasCount)}
255
+
256
+ ${divider}
257
+ ${colors.dim('Keep shipping! ๐Ÿš€')}
258
+ `
259
+ }
260
+
261
+ module.exports = {
262
+ colors,
263
+ frames,
264
+ banners,
265
+ animate,
266
+ typeWriter,
267
+ progressBar,
268
+ sparkle,
269
+ formatShip,
270
+ formatFocus,
271
+ formatSuccess,
272
+ formatError,
273
+ formatIdea,
274
+ formatCleanup,
275
+ formatRecap,
276
+ catppuccin,
277
+ }