mells-cli 1.0.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.
Binary file
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Mells CLI
2
+
3
+ Interactive command-line portfolio tool.
4
+
5
+ ## Installation
6
+
7
+ Run directly with npx (no installation required):
8
+
9
+ ```bash
10
+ npx mells-cli
11
+ ```
12
+
13
+ Or install globally:
14
+
15
+ ```bash
16
+ npm install -g mells-cli
17
+ mells-cli
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ Once launched, type `help` to see available commands.
23
+
24
+ ## Commands
25
+
26
+ - `help` - Show available commands
27
+ - `about` - Learn about me
28
+ - `skills` - View technical skills
29
+ - `projects` - See featured projects
30
+ - `journey` - My CLI & DevOps journey
31
+ - `why-hire-me` - Why you should hire me
32
+ - `resume` - Open resume in browser
33
+ - `contact` - Get contact information
34
+ - `clear` - Clear the screen
35
+ - `exit` - Exit the CLI
36
+
37
+ ## Requirements
38
+
39
+ - Node.js >= 18.0.0
40
+
41
+ ## License
42
+
43
+ MIT
package/Resume.pdf ADDED
Binary file
package/bin/index.js ADDED
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk';
4
+ import readline from 'readline';
5
+ import ora from 'ora';
6
+ import {
7
+ helpCommand,
8
+ aboutCommand,
9
+ skillsCommand,
10
+ projectsCommand,
11
+ journeyCommand,
12
+ whyHireMeCommand,
13
+ contactCommand,
14
+ clearCommand,
15
+ easterEgg
16
+ } from '../commands/handlers.js';
17
+ import { resumeCommand } from '../commands/resume.js';
18
+ import { printHeader, printError, sleep, typeWriter } from '../utils/display.js';
19
+ import { showAnimatedBanner, showQuietBanner } from '../utils/banner.js';
20
+
21
+ const showWelcome = async () => {
22
+ console.clear();
23
+
24
+ // Copilot style spinner
25
+ const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
26
+ let i = 0;
27
+
28
+ const interval = setInterval(() => {
29
+ process.stdout.write(`\r ${chalk.cyan(frames[i++ % frames.length])} Initializing...`);
30
+ }, 80);
31
+
32
+ await sleep(1500);
33
+ clearInterval(interval);
34
+ process.stdout.write('\r' + ' '.repeat(50) + '\r\n');
35
+
36
+ await showAnimatedBanner();
37
+
38
+ console.log(chalk.white(' Type ') + chalk.green.bold('help') + chalk.white(' to see available commands'));
39
+ console.log(chalk.dim(' Type ') + chalk.green.bold('exit') + chalk.dim(' to quit\n'));
40
+ };
41
+
42
+ const processCommand = async (input) => {
43
+ const command = input.trim().toLowerCase();
44
+
45
+ if (!command) return true;
46
+
47
+ const spinner = ora({ text: 'Processing...', color: 'cyan', spinner: 'dots' });
48
+
49
+ // Command suggestions for typos
50
+ const suggestions = {
51
+ 'skill': 'skills',
52
+ 'project': 'projects',
53
+ 'hire': 'why-hire-me',
54
+ 'quit': 'exit',
55
+ 'cls': 'clear',
56
+ 'ls': 'help',
57
+ 'info': 'about',
58
+ 'cv': 'resume'
59
+ };
60
+
61
+ if (suggestions[command]) {
62
+ console.log(chalk.yellow(`\n💡 Did you mean "${suggestions[command]}"? Running it...\n`));
63
+ await sleep(400);
64
+ return await processCommand(suggestions[command]);
65
+ }
66
+
67
+ switch (command) {
68
+ case 'help':
69
+ await helpCommand();
70
+ break;
71
+ case 'about':
72
+ await aboutCommand();
73
+ break;
74
+ case 'skills':
75
+ await skillsCommand();
76
+ break;
77
+ case 'projects':
78
+ await projectsCommand();
79
+ break;
80
+ case 'journey':
81
+ await journeyCommand();
82
+ break;
83
+ case 'why-hire-me':
84
+ await whyHireMeCommand();
85
+ break;
86
+ case 'resume':
87
+ await resumeCommand();
88
+ break;
89
+ case 'contact':
90
+ await contactCommand();
91
+ break;
92
+ case 'clear':
93
+ clearCommand();
94
+ break;
95
+ case 'exit':
96
+ case 'quit':
97
+ spinner.start('Shutting down...');
98
+ await sleep(600);
99
+ spinner.succeed(chalk.green('Thanks for visiting!'));
100
+ console.log(chalk.dim(' Good luck with your search.\n'));
101
+ return false;
102
+ case 'whoami':
103
+ case 'sudo hire-mells':
104
+ case 'coffee':
105
+ await easterEgg(command);
106
+ break;
107
+ default:
108
+ printError(`Command not found: "${input}". Type "help" for available commands.`);
109
+ }
110
+
111
+ return true;
112
+ };
113
+
114
+ const startCLI = async () => {
115
+ await showWelcome();
116
+
117
+ const rl = readline.createInterface({
118
+ input: process.stdin,
119
+ output: process.stdout,
120
+ prompt: chalk.green.bold('❯ '),
121
+ terminal: process.stdin.isTTY
122
+ });
123
+
124
+ let processing = false;
125
+
126
+ rl.prompt();
127
+
128
+ rl.on('line', async (input) => {
129
+ if (processing) return;
130
+ processing = true;
131
+
132
+ try {
133
+ const shouldContinue = await processCommand(input);
134
+
135
+ if (shouldContinue) {
136
+ rl.prompt();
137
+ } else {
138
+ rl.close();
139
+ }
140
+ } catch (error) {
141
+ console.error(chalk.red('Error:'), error);
142
+ rl.prompt();
143
+ } finally {
144
+ processing = false;
145
+ }
146
+ });
147
+
148
+ rl.on('close', () => {
149
+ process.exit(0);
150
+ });
151
+
152
+ rl.on('SIGINT', () => {
153
+ console.log(chalk.yellow('\n\n Use "exit" to quit gracefully.\n'));
154
+ rl.prompt();
155
+ });
156
+ };
157
+
158
+ startCLI().catch(error => {
159
+ console.error(chalk.red('✖ Error starting CLI:'), error);
160
+ process.exit(1);
161
+ });
@@ -0,0 +1,75 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { content } from '../data/content.js';
4
+ import { printHeader, printSection, printSuccess, printBox, sleep, typeWriter } from '../utils/display.js';
5
+
6
+ export const helpCommand = async () => {
7
+ printHeader('Available Commands');
8
+
9
+ const commands = [
10
+ ['help', 'Show this help message'],
11
+ ['about', 'Learn about me'],
12
+ ['skills', 'View my technical skills'],
13
+ ['projects', 'See my featured projects'],
14
+ ['journey', 'My CLI & DevOps journey'],
15
+ ['why-hire-me', 'Why you should hire me'],
16
+ ['resume', 'Open my resume'],
17
+ ['contact', 'Get my contact info'],
18
+ ['clear', 'Clear the screen'],
19
+ ['exit', 'Exit the CLI']
20
+ ];
21
+
22
+ for (const [cmd, desc] of commands) {
23
+ console.log(chalk.cyan(' ' + cmd.padEnd(15)) + chalk.white('→ ' + desc));
24
+ await sleep(50);
25
+ }
26
+
27
+ console.log(chalk.dim.italic('\n 💡 Hint: Try some hidden commands too...\n'));
28
+ };
29
+
30
+ export const aboutCommand = async () => {
31
+ await printSection('About Me', content.about);
32
+ };
33
+
34
+ export const skillsCommand = async () => {
35
+ await printSection('Technical Skills', content.skills);
36
+ };
37
+
38
+ export const projectsCommand = async () => {
39
+ await printSection('Featured Projects', content.projects);
40
+ };
41
+
42
+ export const journeyCommand = async () => {
43
+ await printSection('My Journey', content.journey);
44
+ };
45
+
46
+ export const whyHireMeCommand = async () => {
47
+ await printSection('Why Hire Me', content.whyHireMe);
48
+ };
49
+
50
+ export const contactCommand = async () => {
51
+ console.log('\n' + chalk.cyan.bold('Contact Information'));
52
+ console.log(chalk.cyan('─'.repeat(60)) + '\n');
53
+
54
+ const lines = content.contact.trim().split('\n');
55
+ for (const line of lines) {
56
+ await typeWriter(chalk.white(line), 10);
57
+ console.log();
58
+ await sleep(30);
59
+ }
60
+ console.log();
61
+ };
62
+
63
+ export const clearCommand = () => {
64
+ console.clear();
65
+ printSuccess('Screen cleared!');
66
+ };
67
+
68
+ export const easterEgg = async (command) => {
69
+ const egg = content.easterEggs[command];
70
+ if (egg) {
71
+ console.log(chalk.magenta.bold(`\n${egg}\n`));
72
+ return true;
73
+ }
74
+ return false;
75
+ };
@@ -0,0 +1,16 @@
1
+ import open from 'open';
2
+ import chalk from 'chalk';
3
+ import { content } from '../data/content.js';
4
+ import { printError } from '../utils/display.js';
5
+
6
+ export const resumeCommand = async () => {
7
+ console.log(chalk.cyan('\n⏳ Opening resume in browser...'));
8
+
9
+ try {
10
+ await open(content.resume.url);
11
+ console.log(chalk.green('✔ Resume opened successfully!\n'));
12
+ } catch (error) {
13
+ console.log(chalk.red('✖ Failed to open resume\n'));
14
+ printError('Could not open browser. Please visit: ' + content.resume.url);
15
+ }
16
+ };
@@ -0,0 +1,115 @@
1
+ export const content = {
2
+ about: `
3
+ I'm Melbin Kuriakose, a Computer Science graduate with hands-on DevOps
4
+ training. I specialize in Linux system administration, cloud platforms
5
+ (AWS, GCP), and infrastructure automation. Currently pursuing a
6
+ Postgraduate Diploma in DevOps & Cloud Computing.
7
+
8
+ ✔ Strong foundation in Linux and system administration
9
+ ✔ Hands-on with Docker, Kubernetes, Terraform, and Ansible
10
+ ✔ CI/CD pipeline implementation using Jenkins and GitHub
11
+ ✔ Seeking Linux System Administrator roles
12
+ `,
13
+
14
+ skills: `
15
+ Technical Skills:
16
+
17
+ Languages & Scripting
18
+ • Python, Bash, Shell Scripting
19
+
20
+ Cloud & Infrastructure
21
+ • AWS, GCP, Terraform, Ansible
22
+ • VPC, EC2, ECS, RDS, ALB
23
+
24
+ CI/CD & Automation
25
+ • Jenkins, GitHub, n8n Automation, MCP Servers
26
+
27
+ Containerization & Orchestration
28
+ • Docker, Kubernetes
29
+
30
+ Monitoring & Observability
31
+ • Prometheus, Grafana, Alertmanager
32
+
33
+ Soft Skills
34
+ • Leadership, Creative Thinking, Teamwork
35
+ • Communication, Time Management
36
+ `,
37
+
38
+ projects: `
39
+ Featured Projects:
40
+
41
+ 1. Infrastructure Automation with Terraform
42
+ → Built highly available AWS infrastructure (VPC, EC2, ECS, RDS, ALB)
43
+ → Multi-AZ deployment for fault tolerance
44
+ → Secured with private subnets, NAT, security groups
45
+ → Auto-scaling and least-privilege access
46
+ GitHub: github.com/mellowbricks
47
+
48
+ 2. Ansible Node.js Deployment
49
+ → Automated Ubuntu server provisioning with Ansible
50
+ → IaC-driven deployment for Node.js applications
51
+ → Consistent, repeatable development environments
52
+ → Reduced configuration drift and manual errors
53
+ GitHub: github.com/mellowbricks
54
+
55
+ 3. Jenkins Automated Deployment
56
+ → CI/CD pipeline for Java applications
57
+ → Nexus artifact management + SSH-based EC2 deployment
58
+ → Reduced deployment time from 15 min to under 2 min
59
+ → Zero-touch automation with post-build triggers
60
+ GitHub: github.com/mellowbricks
61
+
62
+ 4. Phishing & Session Hijacking Analysis (Evilginx2)
63
+ → Security research using Evilginx2 on Kali Linux
64
+ → Man-in-the-Middle attack simulation
65
+ → Educational cybersecurity analysis
66
+ `,
67
+
68
+ journey: `
69
+ My DevOps Journey:
70
+
71
+ → Started with Computer Science fundamentals (B.Sc. CGPA: 8.30)
72
+ → Linux Admin Intern at CoreXtech IT Services (Apr-Jul 2025)
73
+ → Completed DevOps & Cloud Computing training (Apr-Nov 2025)
74
+ → Built production-grade infrastructure with Terraform & Ansible
75
+ → Implemented CI/CD pipelines reducing deployment time by 87%
76
+ → Graphics Team Member & E-Publicity Head at PCACS College
77
+ → Completed Deloitte & Accenture job simulations (Forage)
78
+ → Now building this interactive CLI portfolio!
79
+ `,
80
+
81
+ whyHireMe: `
82
+ Why Hire Me?
83
+
84
+ ✔ Proven Track Record → Reduced deployment time by 87% through automation
85
+ ✔ Cloud Native → Hands-on with AWS, GCP, Terraform, Kubernetes
86
+ ✔ Security Minded → Implemented least-privilege access & secure architectures
87
+ ✔ Fast Learner → Completed intensive DevOps training with real projects
88
+ ✔ Team Leader → Led college publicity team, boosted participation by 20%
89
+ ✔ Problem Solver → Built fault-tolerant, auto-scaling infrastructure
90
+
91
+ I don't just write scripts—I build reliable, scalable cloud infrastructure.
92
+ `,
93
+
94
+ contact: `
95
+ Let's Connect:
96
+
97
+ • Email: melbinmk04@gmail.com
98
+ • LinkedIn: linkedin.com/in/melbinkuriakose
99
+ • GitHub: github.com/mellowbricks
100
+ • Portfolio: mellowbricks.co.in
101
+ • Phone: +91 8976345285
102
+ • Location: Thane, Maharashtra
103
+ `,
104
+
105
+ resume: {
106
+ url: 'https://www.mellowbricks.co.in/Resume.pdf',
107
+ message: 'Opening resume in your browser...'
108
+ },
109
+
110
+ easterEggs: {
111
+ whoami: '→ Melbin Kuriakose | Future Linux SysAdmin & DevOps Engineer 🚀',
112
+ 'sudo hire-mells': '✔ Access granted! Initiating hiring process... Welcome aboard! 🎉',
113
+ coffee: '☕ Brewing motivation... 100% ready to automate all the things!'
114
+ }
115
+ };
@@ -0,0 +1,155 @@
1
+ %PDF-1.4
2
+ %���� ReportLab Generated PDF document http://www.reportlab.com
3
+ 1 0 obj
4
+ <<
5
+ /F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R /F5 7 0 R /F6 9 0 R
6
+ >>
7
+ endobj
8
+ 2 0 obj
9
+ <<
10
+ /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
11
+ >>
12
+ endobj
13
+ 3 0 obj
14
+ <<
15
+ /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
16
+ >>
17
+ endobj
18
+ 4 0 obj
19
+ <<
20
+ /BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
21
+ >>
22
+ endobj
23
+ 5 0 obj
24
+ <<
25
+ /BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font
26
+ >>
27
+ endobj
28
+ 6 0 obj
29
+ <<
30
+ /Contents 15 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
31
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
32
+ >> /Rotate 0 /Trans <<
33
+
34
+ >>
35
+ /Type /Page
36
+ >>
37
+ endobj
38
+ 7 0 obj
39
+ <<
40
+ /BaseFont /Symbol /Name /F5 /Subtype /Type1 /Type /Font
41
+ >>
42
+ endobj
43
+ 8 0 obj
44
+ <<
45
+ /Contents 16 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
46
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
47
+ >> /Rotate 0 /Trans <<
48
+
49
+ >>
50
+ /Type /Page
51
+ >>
52
+ endobj
53
+ 9 0 obj
54
+ <<
55
+ /BaseFont /ZapfDingbats /Name /F6 /Subtype /Type1 /Type /Font
56
+ >>
57
+ endobj
58
+ 10 0 obj
59
+ <<
60
+ /Contents 17 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
61
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
62
+ >> /Rotate 0 /Trans <<
63
+
64
+ >>
65
+ /Type /Page
66
+ >>
67
+ endobj
68
+ 11 0 obj
69
+ <<
70
+ /Contents 18 0 R /MediaBox [ 0 0 612 792 ] /Parent 14 0 R /Resources <<
71
+ /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
72
+ >> /Rotate 0 /Trans <<
73
+
74
+ >>
75
+ /Type /Page
76
+ >>
77
+ endobj
78
+ 12 0 obj
79
+ <<
80
+ /PageMode /UseNone /Pages 14 0 R /Type /Catalog
81
+ >>
82
+ endobj
83
+ 13 0 obj
84
+ <<
85
+ /Author (\(anonymous\)) /CreationDate (D:20260222103249+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260222103249+00'00') /Producer (ReportLab PDF Library - www.reportlab.com)
86
+ /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False
87
+ >>
88
+ endobj
89
+ 14 0 obj
90
+ <<
91
+ /Count 4 /Kids [ 6 0 R 8 0 R 10 0 R 11 0 R ] /Type /Pages
92
+ >>
93
+ endobj
94
+ 15 0 obj
95
+ <<
96
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 1126
97
+ >>
98
+ stream
99
+ GauI59lJcG&;KZL'm!Nn?.c/Jad0T[D:75A=X9K8kf"?m@OsDMl&q:eo[iP.ri"jJEiR$oJ0Bk'^(6"f%#7*(+4>Q.$K05=hL?e9-tJB(iZO!B)QpB(D\lsYcQn4tSDp.q(,dnR]YN.?@3p<!_Gr"Ge?;3<?Xk/$P:?KujY6O$Pbj'Ef:QFP[moO<GAnqDe^B7G-thL:o@cFF@WZs@\TmiYZEKAg%[3Yf&F*X#]ECn*/m_!,n85[TZg$!"N^s./CLPdlD"d.rMDT3L%!r`2:(m.<2NgdhNm]+'0Ek?7@2O3//V*/e@Oe"7;@-H>iuW=l2)q^2E!:<ub#3./(r8ounN@965]-IPdicB.8o4^8rE_r5=-GXc@R2HNYVQ&PQ3,Yn\m?/f!8"0F@cc[%=crRrKTST@&bP0p]!]Ol2!rNmD,&(6"s,e@eEW*$dA0ca('RG1[p('u[AfO7,/7]D[:2N[#gt:q"H@EM?u#qRq@8cTRgCb0$]^R"e",?0SBccDHKhY$<f"a(-*%b6`%+L5!h!Fp#X$`8OK8=O5;<)D`3WG=)!mGSqQW9GYC\i`1;[LON=Tnl1I.dV=luM\r?k91lSdc`l/-*"S^@H:d]Bg(P&W6oQe\5&Y8M+AOp(1\^#A0kYg-piCbjf\!V[pjm_tT;i5ENQ/k)TOU0p:HoD3'1hd9#VU[b/&X`1s9;$RUPc@]tZ/TY_Fkkn$lp40j8fR/Gie-e`,^r#&<=/o^)+cN!`bS^%:oXs+i2_M0X""`%fW+b#t'rAgA^1d*@N#QUcI),p&:-=8gnXKD11rn5VeD]gDSdm3J."I8EV/Xd<csGg^B0)$9A8j$dIU59tOV>B(P-YdKK2GfH%[!BMH7N.N:.FEaao7Sq@\Mg>b*HZQ6dlP@A@VPMKlpn,FO.bn8m:QZC4mZ_cI'isBVr[]YfDPtYKeT;*QmHeQ.Bit3.R'7Qha6B9,p`T]b"WL]h7.+)"D%'h*I."fj?1@HJ:QMFm)TH>]f@Is0/'PH3Y<#G=Y2P'*%u$)+&OnVf>&4nR(&IV6m:d4^6Qp&dMQj#hEGsiabs^Tli<L@aDuADK,T)ERPb1X^(<c6Gdp$,^g?n.t^[nF9HROkH#>B\G-Rd*Ah"~>endstream
100
+ endobj
101
+ 16 0 obj
102
+ <<
103
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 1140
104
+ >>
105
+ stream
106
+ GatUrD3*C1&BE]".H\lHD3(uJ,b\*d[<oO;Pu&Q?WH9do3Z2Q108Z7-P@aR`*@K3?&M[K6U_"N$s3Ka*N5l0a5(7S7"i,m2>[70a#;BA4+,qJ3:#ThFGSp4fR7RaB2l=]LYJ6*X-cmd@j*uI(\59bE<JB*BVV/b#B'JE-rdOl:3/19;Z\%g98?H-3Io#%B48A7jbjJp5asnL5UcXjZnK`"m+-*@H&@>WJ2Qp7fctM828HS?@a0GcLMLrsor$$S<1[^?cc^2CW#!ke4dYLLXU/O;Ack"ISs%&'n/\r[T77Q0G?,9DpNf,sE[n`Hd"3:#*KbOE(>([KJ6F]u5l#M)#iXR?S4e/an]S*m>(dfq"o,J?d3$ReL#W>bk"V$6KPu_&4/"n6D]st]Y;q2c.C'Zq'F[f`m3GO2ZetUk.i@fTV>ai9k:?E$&`B@I:efrF7$Z/pZ"&gB/-fS!NNHtjCX,YPC+dYR+SDHN-<,Ql;E3aXh/G@D&/[`/[?CCh1F^T-_T2.A>>![ji7Iau;m3M=a'1S2W$1Clr-#QpP)m8qIL]K])\^ISL_k1=(9$o9Y0PZ0%43L.DOY]jqSCt!PY?+'NlN2:B:QC]5TP@B"%;;_W>uT/Xer`BuO"A^ml91=\;=4[BKXk,&KA&oHOX!_a*8sMQR<G!X"V^^YVTBa_)``Sd7J3pW4./-M+mP0t4@c8QUA!/WNTf6#%`=&b%$+1n*uB8oQ?Npo*Bjtn`(^fN"@7+g&4,&j`$;d$VEt_nbN6&?T.ohs!sFf/M545sTTQptNXo_)nTafhi*EjqX.%=-.f?csWV45p>RH=*H\Xo-!ke+@@-UG%Xq]Npi3ucs)_ki=mieZQFQ.YfnUpI]I'+4m`8@KlTQ*?>)AJ(?2g24L"_e3eI%k15DVagg^AWEKm0<R+LRLP::i#!2DQp<OLZ:[FIKuq;8AYe6CU(Q_D/;3,MWN-)1[mIs]^n^,gX9gm.>h^b%,GNW/!a%njFZnLa'nnQ7p)^]8h_RO/Q5.;j_9gP"!fp)>`\b,)8V9C(b%GfTC!5??c<Mqr=e;cGVF#P#PA9bW=2;k#2[&d;l@3N>^^XYpf,HpUX$rnBcT40o=p-6^<j5+3E=3F:d[*VH3>$cq?%*0hZ;&EN`Q~>endstream
107
+ endobj
108
+ 17 0 obj
109
+ <<
110
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 951
111
+ >>
112
+ stream
113
+ GatUr9lJc?%#46H'tat=L=WWjmp_V9CPQ?;RNWPpfu7s\<37a!P2%A`I['5A88;q=$Ni]3LjC/*'PRV$5,A"u$@koFQsL@I'UEr.I)h$(2-_a]^F,g])9!/t'GmOhD/=5K5r\AI'D`L3/oJ!'21(k;A?"']Q)FJ]Pf5Z<Ej77sW)G+mlt15Ef3Hh[pTT$qjThRU".o\G0_(.fYr1rO?6Zbns$6:bE&)(S5boT6kFcoHF^;gRoMR4j`EHD!U0\8c[tVb=6UEN'9h=7j,d@Gm=['&`_a;O-e$W^eBc?_:#>sD90mGXDX>uTtCctR*g'cqpi;6:)!dP=rT%Ib.$C9l?/Bdj2O"n<T&!mPFRf?^h_MX7#k*0_R#;s@].go%l>)eZI2:"cQY#Cld1$+i14V#(rZc@1*d('hq\NA#4f]D>LmWJ6T'i*c(XG)B^2.*\[$YD!EJ0b*iDIhAf^WXA_'Yu`J.a4@&\?]/;TCcprnTaGnMSZ=<F/GY3GV1mTLhHc4HlIam'rs)kORksH?&=5iC]2P+[)IK:E3qD1_>sldC-?&\E(6:T.5KmDY[CTc\_``p;cm]geJu>,.>ZSOiKDTNra#Z\C*lB<K?>IC2#]s$"(Pj2P("0"*m\jOnf<r0'7_Z=@Ah*"MaqPR]P%9i*05+0<:Vol.nkl`:Sn\cV1:DGR'OU4"#/4D<@,S7c`G:4?")I76F4fe^[F-PFrD`'po5cTf(TV.;&)pXX.66f4UBcMn3#K\gGFmNLh"'Sfj>U9lG-D:VE.t>Hh4[S@UooYot5_T9'c\h;Sd.Tdl^Q2YrJlbdjZ^`+E5@7/FW,ieoR%N?^8QJ3-VLJZb"!kcTm_`hf1!F%+,&B31f)pXmgoti&IhtD>1C]"9SqZ)c_E[!uKT%.W(%RB%Y7ojJeCEmq3_.&r_jem.r6R=t"XT.H!q-aiD`m0_l*_am9!~>endstream
114
+ endobj
115
+ 18 0 obj
116
+ <<
117
+ /Filter [ /ASCII85Decode /FlateDecode ] /Length 244
118
+ >>
119
+ stream
120
+ Gat=d0b8ji&;BlXMDqPl8eEMT)P(+i20!SL&/7K9U_*R?/J8^+@3ColnFH!qG=UWFU.p[pYi_>A.&[ZJJd/O]I#fj,:I885MnhI4R]Y^0>'V?9N.-uWXSel=9oABp7Mj2a2Hi_HXp/UBi[WDLjC@Zapr#H.[XLL#.WD&12&_?:-Dm(8FHJ!#b@R7"E:DPW2J-.RU.TPWHcaH+E\NlN-UQd6`[e+X&1Wm\]tOIB7CrZC)hB2Y]`~>endstream
121
+ endobj
122
+ xref
123
+ 0 19
124
+ 0000000000 65535 f
125
+ 0000000073 00000 n
126
+ 0000000154 00000 n
127
+ 0000000261 00000 n
128
+ 0000000373 00000 n
129
+ 0000000478 00000 n
130
+ 0000000597 00000 n
131
+ 0000000792 00000 n
132
+ 0000000869 00000 n
133
+ 0000001064 00000 n
134
+ 0000001147 00000 n
135
+ 0000001343 00000 n
136
+ 0000001539 00000 n
137
+ 0000001609 00000 n
138
+ 0000001893 00000 n
139
+ 0000001973 00000 n
140
+ 0000003191 00000 n
141
+ 0000004423 00000 n
142
+ 0000005465 00000 n
143
+ trailer
144
+ <<
145
+ /ID
146
+ [<fd51dcc6bed0ec449a0ffaef4eb144c6><fd51dcc6bed0ec449a0ffaef4eb144c6>]
147
+ % ReportLab generated PDF document -- digest (http://www.reportlab.com)
148
+
149
+ /Info 13 0 R
150
+ /Root 12 0 R
151
+ /Size 19
152
+ >>
153
+ startxref
154
+ 5800
155
+ %%EOF
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "mells-cli",
3
+ "version": "1.0.0",
4
+ "description": "Interactive DevOps portfolio CLI - Meet Melbin Kuriakose",
5
+ "type": "module",
6
+ "main": "bin/index.js",
7
+ "bin": {
8
+ "mells-cli": "./bin/index.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node bin/index.js"
12
+ },
13
+ "keywords": ["cli", "portfolio", "devops", "linux", "interactive", "terminal"],
14
+ "author": "Melbin Kuriakose <melbinmk04@gmail.com>",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/mellowbricks/mells-cli"
18
+ },
19
+ "homepage": "https://mellowbricks.co.in",
20
+ "license": "MIT",
21
+ "engines": {
22
+ "node": ">=18.0.0"
23
+ },
24
+ "dependencies": {
25
+ "chalk": "^5.3.0",
26
+ "ora": "^8.0.1",
27
+ "open": "^10.0.3"
28
+ }
29
+ }
package/test-cli.js ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+
3
+ import readline from 'readline';
4
+ import chalk from 'chalk';
5
+
6
+ const rl = readline.createInterface({
7
+ input: process.stdin,
8
+ output: process.stdout,
9
+ prompt: chalk.green('❯ ')
10
+ });
11
+
12
+ console.log('Test CLI - type commands');
13
+ rl.prompt();
14
+
15
+ rl.on('line', async (input) => {
16
+ const cmd = input.trim();
17
+
18
+ if (cmd === 'test') {
19
+ console.log('Test output');
20
+ } else if (cmd === 'exit') {
21
+ console.log('Goodbye');
22
+ rl.close();
23
+ return;
24
+ }
25
+
26
+ rl.prompt();
27
+ });
28
+
29
+ rl.on('close', () => {
30
+ process.exit(0);
31
+ });
@@ -0,0 +1,116 @@
1
+ import chalk from 'chalk';
2
+ import { sleep } from './display.js';
3
+
4
+ const bannerFrames = [
5
+ {
6
+ line1: '███╗ ███╗███████╗██╗ ██╗ ███████╗',
7
+ line2: '████╗ ████║██╔════╝██║ ██║ ██╔════╝',
8
+ line3: '██╔████╔██║█████╗ ██║ ██║ ███████╗',
9
+ line4: '██║╚██╔╝██║██╔══╝ ██║ ██║ ╚════██║',
10
+ line5: '██║ ╚═╝ ██║███████╗███████╗███████╗███████║',
11
+ line6: '╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚══════╝'
12
+ }
13
+ ];
14
+
15
+ const animatedBanner = [
16
+ // Frame 1: Lines slide in from left
17
+ [
18
+ '█ ',
19
+ '██ ',
20
+ '███ ',
21
+ '████ ',
22
+ '█████ ',
23
+ '██████ '
24
+ ],
25
+ // Frame 2
26
+ [
27
+ '███╗ ',
28
+ '████╗ ',
29
+ '██╔██ ',
30
+ '██║╚█ ',
31
+ '██║ ╚ ',
32
+ '╚═╝ '
33
+ ],
34
+ // Frame 3
35
+ [
36
+ '███╗ ███╗ ',
37
+ '████╗ ████║ ',
38
+ '██╔████╔██║ ',
39
+ '██║╚██╔╝██║ ',
40
+ '██║ ╚═╝ ██║ ',
41
+ '╚═╝ ╚═╝ '
42
+ ],
43
+ // Frame 4
44
+ [
45
+ '███╗ ███╗███████╗ ',
46
+ '████╗ ████║██╔════╝ ',
47
+ '██╔████╔██║█████╗ ',
48
+ '██║╚██╔╝██║██╔══╝ ',
49
+ '██║ ╚═╝ ██║███████╗ ',
50
+ '╚═╝ ╚═╝╚══════╝ '
51
+ ],
52
+ // Frame 5
53
+ [
54
+ '███╗ ███╗███████╗██╗ ██╗ ███████╗ ',
55
+ '████╗ ████║██╔════╝██║ ██║ ██╔════╝ ',
56
+ '██╔████╔██║█████╗ ██║ ██║ ███████╗ ',
57
+ '██║╚██╔╝██║██╔══╝ ██║ ██║ ╚════██║ ',
58
+ '██║ ╚═╝ ██║███████╗███████╗███████╗███████║ ',
59
+ '╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚══════╝ '
60
+ ]
61
+ ];
62
+
63
+ export const showAnimatedBanner = async () => {
64
+ const padding = 2;
65
+ const paddingStr = ' '.repeat(padding);
66
+
67
+ // Animate banner drawing
68
+ for (let frame of animatedBanner) {
69
+ console.clear();
70
+ console.log(chalk.cyan('\n'));
71
+ frame.forEach(line => {
72
+ console.log(chalk.cyan(paddingStr + line));
73
+ });
74
+ await sleep(120);
75
+ }
76
+
77
+ // Hold final frame
78
+ await sleep(300);
79
+
80
+ console.log(chalk.cyan(`
81
+ ${chalk.gray('━'.repeat(45))}
82
+
83
+ ${chalk.white('Melbin Kuriakose')}
84
+ ${chalk.white('DevOps Engineer')} ${chalk.dim('|')} ${chalk.white('Linux System Administrator')}
85
+
86
+ ${chalk.dim('CLI v1.0.0')}
87
+ `));
88
+ };
89
+
90
+ export const showQuietBanner = () => {
91
+ const padding = 2;
92
+ const paddingStr = ' '.repeat(padding);
93
+
94
+ const finalFrame = [
95
+ '███╗ ███╗███████╗██╗ ██╗ ███████╗',
96
+ '████╗ ████║██╔════╝██║ ██║ ██╔════╝',
97
+ '██╔████╔██║█████╗ ██║ ██║ ███████╗',
98
+ '██║╚██╔╝██║██╔══╝ ██║ ██║ ╚════██║',
99
+ '██║ ╚═╝ ██║███████╗███████╗███████╗███████║',
100
+ '╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚══════╝'
101
+ ];
102
+
103
+ console.clear();
104
+ console.log(chalk.cyan('\n'));
105
+ finalFrame.forEach(line => {
106
+ console.log(chalk.cyan(paddingStr + line));
107
+ });
108
+ console.log(chalk.cyan(`
109
+ ${chalk.gray('━'.repeat(45))}
110
+
111
+ ${chalk.white('Melbin Kuriakose')} ${chalk.yellow('👋')}
112
+ ${chalk.white('DevOps Engineer')} ${chalk.dim('|')} ${chalk.white('Linux System Administrator')}
113
+
114
+ ${chalk.dim('CLI v1.0.0')}
115
+ `));
116
+ };
@@ -0,0 +1,50 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+
4
+ export const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
5
+
6
+ export const typeWriter = async (text, delay = 15) => {
7
+ for (const char of text) {
8
+ process.stdout.write(char);
9
+ await sleep(delay);
10
+ }
11
+ };
12
+
13
+ export const printHeader = (text) => {
14
+ console.log('\n' + chalk.cyan.bold('═'.repeat(60)));
15
+ console.log(chalk.cyan.bold(` ${text}`));
16
+ console.log(chalk.cyan.bold('═'.repeat(60)) + '\n');
17
+ };
18
+
19
+ export const printSection = async (title, content) => {
20
+ console.log('\n' + chalk.cyan.bold(title));
21
+ console.log(chalk.cyan('─'.repeat(60)) + '\n');
22
+
23
+ const lines = content.trim().split('\n');
24
+ for (const line of lines) {
25
+ await typeWriter(chalk.white(line), 10);
26
+ console.log();
27
+ await sleep(30);
28
+ }
29
+ console.log();
30
+ };
31
+
32
+ export const printError = (message) => {
33
+ console.log(chalk.red.bold(`\n✖ ${message}\n`));
34
+ };
35
+
36
+ export const printSuccess = (message) => {
37
+ console.log(chalk.green.bold(`\n✔ ${message}\n`));
38
+ };
39
+
40
+ export const printBox = (lines) => {
41
+ const maxLen = Math.max(...lines.map(l => l.length));
42
+ const width = maxLen + 4;
43
+
44
+ console.log(chalk.cyan('┌' + '─'.repeat(width) + '┐'));
45
+ lines.forEach(line => {
46
+ const padding = ' '.repeat(width - line.length - 2);
47
+ console.log(chalk.cyan('│ ') + chalk.white(line) + padding + chalk.cyan(' │'));
48
+ });
49
+ console.log(chalk.cyan('└' + '─'.repeat(width) + '┘'));
50
+ };