feat(chat): CLI easter egg with 17 commands + Konami dev-mode + matrix rain

This commit is contained in:
jae 2026-04-20 01:34:57 +00:00
parent 33dfb3410b
commit ee8d313403
5 changed files with 601 additions and 0 deletions

View file

@ -1,6 +1,25 @@
{
"site": "jaeswift.xyz",
"entries": [
{
"version": "1.37.1",
"date": "20/04/2026",
"category": "FEATURE",
"title": "JAE-AI CLI Easter Egg — Local Pseudo-Shell",
"changes": [
"JAE-AI chat now detects messages starting with / and handles them locally as a fake CLI shell — never hits the Venice API, all 100% client-side JavaScript",
"New js/chat-cli.js + css/chat-cli.css — 17 built-in commands: /help /ls /cat <file> /whoami /uptime /uname -a /date /ping <host> /sudo <cmd> /rm -rf / /hack <target> /matrix /clear /exit /fortune /history /neofetch",
"Virtual filesystem: /cat about.md|projects.json|skills.md|secrets.enc|mascot.txt|whoami.txt — with glitchy ASCII art ACCESS DENIED screen on secrets.enc",
"/whoami pulls real data from /api/visitor/scan; /uptime pulls from /api/telemetry/overview; /neofetch shows ASCII dragon with browser/OS/screen data",
"/matrix toggles a full-screen green Katakana matrix-rain canvas overlay (opacity 18%, 16px JetBrains Mono, var(--status-green))",
"/hack runs hollywood-style fake progress bars with payload injection drama before revealing it was all fake",
"/rm -rf / shows an ASCII destruction sequence then restores from backup with a cheeky message",
"Unknown commands route to: command not found: /<cmd>. Type /help for available commands.",
"Persistent /history ring-buffer (50 entries) stored in localStorage.jaeCliHist",
"BONUS: Konami code (↑↑↓↓←→←→BA) unlocks DEVELOPER MODE — amber badge top-right + extra commands: /api (list real endpoints), /curl <url> (actually fetch public URLs, 2KB truncated), /geo (pull live 24h country breakdown from telemetry)",
"chat.js sendMessage() patched to intercept /-prefix messages before hitting /api/chat — user bubble gets $ shell prompt, response styled in terminal-green monospace"
]
},
{
"version": "1.37.0",
"date": "20/04/2026",

42
css/chat-cli.css Normal file
View file

@ -0,0 +1,42 @@
/* ===================================================
JAESWIFT.XYZ JAE-AI CLI output styling
=================================================== */
.chat-msg-cli {
font-family: var(--font-mono);
}
.chat-msg-cli .chat-msg-label {
color: var(--warning);
}
.chat-msg-cli .chat-msg-body {
color: var(--status-green);
font-family: var(--font-mono);
white-space: pre-wrap;
line-height: 1.4;
font-size: 12.5px;
text-shadow: 0 0 4px #00cc3340;
}
.chat-msg-user-cli .chat-msg-label {
color: var(--status-green);
}
.chat-msg-user-cli .chat-msg-body {
color: #e8e8e8;
font-family: var(--font-mono);
font-weight: 500;
}
.chat-msg-user-cli .chat-msg-body::before {
content: '$ ';
color: var(--status-green);
font-weight: 700;
}
#devModeBadge:hover {
background: rgba(201,162,39,0.15) !important;
box-shadow: 0 0 22px rgba(201,162,39,0.6) !important;
}
@media (max-width: 600px) {
.chat-msg-cli .chat-msg-body { font-size: 11px; }
#devModeBadge { font-size: 9px !important; top: 62px !important; padding: 4px 9px !important; }
}

View file

@ -7,6 +7,7 @@
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/chat-memory.css">
<link rel="stylesheet" href="/css/scan-visitor.css">
<link rel="stylesheet" href="/css/chat-cli.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700;800;900&family=Share+Tech+Mono&display=swap" rel="stylesheet">
@ -588,6 +589,7 @@
<script src="/js/wallet-connect.js"></script>
<script src="/js/nav.js"></script>
<script src="/js/chat-memory.js"></script>
<script src="/js/chat-cli.js"></script>
<script src="/js/chat.js"></script>
<script src="/js/globe.js"></script>
<script src="/js/processes.js"></script>

510
js/chat-cli.js Normal file
View file

@ -0,0 +1,510 @@
/* ===================================================
JAESWIFT.XYZ JAE-AI CLI Easter Egg
Local pseudo-shell handled in the JAE-AI chat panel.
Intercepts messages starting with '/'.
=================================================== */
(function () {
'use strict';
const MAX_HISTORY = 50;
const HIST_KEY = 'jaeCliHist';
let cmdHistory = [];
let devMode = false;
let matrixActive = false;
// Load history
try {
const raw = localStorage.getItem(HIST_KEY);
if (raw) cmdHistory = JSON.parse(raw) || [];
} catch (e) {}
function saveHistory() {
try {
localStorage.setItem(HIST_KEY, JSON.stringify(cmdHistory.slice(-MAX_HISTORY)));
} catch (e) {}
}
// ─── Virtual FS ──────────────────────────────────
const VFS = {
'about.md': [
'# JAESWIFT // OPERATOR FILE',
'',
'Codename: JAE',
'Location: Manchester, United Kingdom',
'Operator since: 2008',
'',
'Full-stack engineer, cyber-curious, builds things.',
'Specialisms: Node / Python / Linux / nginx / Solana',
'',
'This site is my HUD. Built by hand, deployed by git, watched by me.',
].join('\n'),
'projects.json': JSON.stringify({
'jaeswift.xyz': 'This site — military CRT HUD, Flask+vanilla',
'matty.lol': 'Crypto/Solana toolkit (Node/Express)',
'contraband-depot': 'FMHY mirror, 24 categories, 16k+ links',
'recon-awesomelist': '28 sectors / 135k items, weekly sync',
'unredacted-vault': '114+ declassified PDFs (MOD/CIA/etc)',
'radar': 'RSS aggregator (HN/Reddit/Lobsters)',
'sitrep': 'Daily AI briefing generator',
'telemetry': 'Live ops command centre'
}, null, 2),
'skills.md': [
'# FIELD LOADOUT',
'',
'## LANGS',
' - Python, JavaScript/Node, TypeScript, Rust, Bash, SQL',
'',
'## STACKS',
' - Flask, Express, React, Solana/Anchor, Docker, systemd',
'',
'## INFRA',
' - nginx, Debian, PostgreSQL, Redis, cron, fail2ban',
'',
'## OPS',
' - VPS ops, CI/CD via Gitea, observability, hardening'
].join('\n'),
'secrets.enc': [
'',
' ░█████╗░░█████╗░░█████╗░███████╗░██████╗░██████╗',
' ██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝██╔════╝',
' ███████║██║░░╚═╝██║░░╚═╝█████╗░░╚█████╗░╚█████╗░',
' ██╔══██║██║░░██╗██║░░██╗██╔══╝░░░╚═══██╗░╚═══██╗',
' ██║░░██║╚█████╔╝╚█████╔╝███████╗██████╔╝██████╔╝',
' ╚═╝░░╚═╝░╚════╝░░╚════╝░╚══════╝╚═════╝░╚═════╝░',
'',
' ▓▒░ ACCESS DENIED ░▒▓',
' File encrypted with AES-4096-QUANTUM-ROT13.',
' Authorisation required. >> /sudo',
].join('\n'),
'mascot.txt': [
' ___ ___',
' ,-" `. ," `-,',
' / _ \\_____/ _ \\',
' | (o) ` ` (o) |',
' \\ \\_._ _._/ /',
' `._ `----\' _.\'',
' `~---------~\'',
' // JAE MASCOT //',
' Black dragon, on duty.'
].join('\n'),
'whoami.txt': '$USER — check /whoami for your details.'
};
// ─── Helpers ─────────────────────────────────────
function fmt(lines) { return Array.isArray(lines) ? lines.join('\n') : lines; }
function pad(n, len) {
const s = String(n);
return s.length >= len ? s : ' '.repeat(len - s.length) + s;
}
async function fakeProgress(label, steps, delay) {
const out = [];
for (let i = 1; i <= steps; i++) {
const pct = Math.floor((i / steps) * 100);
const filled = '█'.repeat(Math.floor(pct / 5));
const empty = '░'.repeat(20 - filled.length);
out.push(`${label} [${filled}${empty}] ${pct}%`);
// intentionally not awaited — output comes as a block
}
return out;
}
// ─── Commands ────────────────────────────────────
const commands = {};
commands.help = function () {
const base = [
'JAE-AI TERMINAL — available commands:',
'',
' /help show this help',
' /ls list virtual files',
' /cat <file> print file contents',
' /whoami show your visitor fingerprint',
' /uptime show site uptime',
' /uname kernel/system info',
' /date current date/time',
' /ping <host> fake ping sweep',
' /sudo <cmd> attempt privilege escalation',
' /rm -rf / don\'t do it',
' /hack <target> hollywood hacking simulator',
' /matrix toggle matrix rain',
' /clear clear the chat',
' /exit try to leave',
' /fortune random sitrep quip',
' /history show last commands',
' /neofetch system summary ASCII',
];
if (devMode) {
base.push('');
base.push(' [DEVELOPER MODE ACTIVE]');
base.push(' /api list real API endpoints');
base.push(' /curl <url> actually fetch a URL');
base.push(' /geo show GEO INTEL from telemetry');
}
base.push('');
base.push('Anything not prefixed with / goes to JAE-AI.');
return fmt(base);
};
commands.ls = function () {
return fmt([
'total 6',
'-rw-r--r-- 1 jae jae 412 apr 20 01:24 about.md',
'-rw-r--r-- 1 jae jae 528 apr 20 01:24 projects.json',
'-rw-r--r-- 1 jae jae 394 apr 20 01:24 skills.md',
'-r-------- 1 jae jae 999 apr 20 01:24 secrets.enc',
'-rw-r--r-- 1 jae jae 210 apr 20 01:24 mascot.txt',
'-rw-r--r-- 1 jae jae 42 apr 20 01:24 whoami.txt'
]);
};
commands.cat = function (args) {
const name = args[0];
if (!name) return 'cat: missing operand — try /cat about.md';
if (VFS[name] != null) return VFS[name];
return `cat: ${name}: No such file or directory`;
};
commands.whoami = async function () {
try {
const r = await fetch('/api/visitor/scan');
if (!r.ok) throw new Error('scan unavailable');
const d = await r.json();
return fmt([
`operator: ${d.ip_masked}`,
`geolocation: ${d.city ? d.city + ', ' : ''}${d.country} ${d.country_flag || ''}`,
`network: ${d.isp}`,
`browser: ${d.browser} ${d.browser_version || ''}`,
`os: ${d.os} ${d.os_version || ''}`,
`device: ${d.device}`,
`threat: ${d.threat_level}${d.threat_reason}`,
'',
'you are a visitor. welcome.'
]);
} catch (e) {
return 'scan service unavailable. try again in a moment.';
}
};
commands.uptime = async function () {
try {
const r = await fetch('/api/telemetry/overview');
const d = await r.json();
const up = (d.system && d.system.uptime) || d.uptime || 'unknown';
const load = (d.system && d.system.load_1) || '—';
const users = 'many';
const now = new Date().toLocaleTimeString('en-GB');
return fmt([
` ${now} up ${up}, ${users} users, load average: ${load}`,
` HQ: Manchester // jaeswift-api.service ● ONLINE`
]);
} catch (e) {
return `up since boot — tired but operational`;
}
};
commands.uname = function (args) {
if (args[0] === '-a') {
return 'Linux jaeswift 6.1.0-jaeswift #1 SMP PREEMPT_DYNAMIC 2026-04-20 x86_64 GNU/Linux';
}
return 'Linux';
};
commands.date = function () {
return new Date().toUTCString();
};
commands.ping = function (args) {
const host = args[0] || 'jaeswift.xyz';
const out = [`PING ${host} (10.0.0.1) 56(84) bytes of data.`];
for (let i = 0; i < 4; i++) {
const t = (10 + Math.random() * 40).toFixed(2);
out.push(`64 bytes from ${host}: icmp_seq=${i+1} ttl=54 time=${t} ms`);
}
out.push('');
out.push(`--- ${host} ping statistics ---`);
out.push('4 packets transmitted, 4 received, 0% packet loss, time 3006ms');
return fmt(out);
};
commands.sudo = function (args) {
if (!args.length) return 'usage: /sudo <command>';
return fmt([
`[sudo] password for operator: ****`,
``,
`sudo: ACCESS DENIED — nice try.`,
`This incident will be reported... actually, no it won\'t.`
]);
};
commands.rm = function (args) {
if (args.join(' ') === '-rf /' || args.join(' ').startsWith('-rf /')) {
return fmt([
' __ __',
' / \\_/ \\ 💥 FORMATTING /dev/sda ...',
' \\_( • )_/ 💥 WIPING /home ...',
' //( )\\\\ 💥 DELETING /etc/passwd ...',
'',
' ERROR: The file system is screaming.',
' ███████████░░░░░░░░░ 58%',
'',
' ... just kidding.',
' SYSTEM RESTORED FROM BACKUP. Nice try, operator.'
]);
}
return `rm: refuse to do whatever that is`;
};
commands.hack = function (args) {
const target = args.join(' ') || 'the-gibson';
return fmt([
`>>> TARGETING ${target}...`,
`>>> BYPASSING FIREWALL... [████████████░░░░] 72%`,
`>>> CRACKING PASSWORD... [████████████████] 100%`,
`>>> INJECTING PAYLOAD... [████████████████] 100%`,
`>>> COVERING TRACKS... [████████████████] 100%`,
``,
`>>> CONNECTION ESTABLISHED.`,
`>>> ACCESS GRANTED TO ${target.toUpperCase()}.`,
``,
`... just kidding lol. nothing was hacked.`,
`If you came here looking for real offsec — go read /cat skills.md and touch grass.`
]);
};
commands.matrix = function () {
matrixActive = !matrixActive;
toggleMatrix(matrixActive);
return matrixActive
? 'Matrix rain enabled. Follow the white rabbit.'
: 'Matrix rain disabled. Back to the desert of the real.';
};
commands.clear = function () {
const cm = document.getElementById('chatMessages');
if (cm) cm.innerHTML = '';
return null; // nothing to print
};
commands.exit = function () {
return fmt([
'logout',
'',
'NICE TRY. You don\'t leave that easily.',
'JAE-AI resumes normal operation.'
]);
};
const FORTUNES = [
'SITREP: quiet on the wire. unusual.',
'SITREP: nothing is fine. everything is broken. proceed.',
'SITREP: coffee low. deploy anyway.',
'SITREP: the logs know. the logs always know.',
'SITREP: git status is a lifestyle.',
'SITREP: ship it friday. regret it monday.',
'SITREP: 99 bugs on the wall, patch one down, 117 on the wall.',
'SITREP: if it works on the VPS, the VPS is now production.',
'SITREP: the only safe deploy is no deploy.',
'SITREP: trust nothing. grep everything.',
];
commands.fortune = function () {
return FORTUNES[Math.floor(Math.random() * FORTUNES.length)];
};
commands.history = function () {
if (!cmdHistory.length) return '(no history yet)';
const recent = cmdHistory.slice(-10);
return recent.map((c, i) => ` ${pad(cmdHistory.length - recent.length + i + 1, 4)} ${c}`).join('\n');
};
commands.neofetch = function () {
const cc = (navigator.language || 'en').toUpperCase();
const ua = navigator.userAgent || '';
let browser = 'Unknown';
if (/firefox/i.test(ua)) browser = 'Firefox';
else if (/edg/i.test(ua)) browser = 'Edge';
else if (/chrome/i.test(ua)) browser = 'Chrome';
else if (/safari/i.test(ua)) browser = 'Safari';
return fmt([
' ▄███████▄ operator@jaeswift.xyz',
' ██░░░░░░░██ ----------------------',
' ██░░░░░░░██ OS: JAESWIFT/6.1.0 x86_64',
' ██░██░██░██ Host: Manchester HQ',
' ██░░░░░░░██ Kernel: CRT-tactical-v2',
' ██░░░░░██ Uptime: 24/7/365',
' ███████ Shell: /bin/jaesh',
' █ █ Resolution: ' + screen.width + 'x' + screen.height,
' ██ ██ Terminal: JAE-AI',
' ██ ██ Browser: ' + browser,
' Locale: ' + cc,
' CPU: 18-core @ spicy GHz',
' Memory: 96GB tactical',
' Theme: mil-green/CRT/cyberpunk',
]);
};
// ─── Dev-mode commands ──────────────────────────
commands.api = async function () {
if (!devMode) return 'command not found. try /help';
const endpoints = [
'/api/visitor/scan',
'/api/visitor/recent-arcs',
'/api/leaderboards',
'/api/telemetry/overview',
'/api/telemetry/history',
'/api/telemetry/geo',
'/api/telemetry/visitors',
'/api/telemetry/nginx-tail',
'/api/telemetry/alerts',
'/api/stats',
'/api/navigation',
'/api/changelog',
'/api/chat (POST)',
'/api/contraband',
'/api/sitrep/latest',
'/api/radar'
];
return 'JAESWIFT API endpoints (dev-mode):\n\n ' + endpoints.join('\n ');
};
commands.curl = async function (args) {
if (!devMode) return 'command not found. try /help';
const url = args[0];
if (!url) return 'usage: /curl <url>';
try {
const r = await fetch(url);
const text = (await r.text()).slice(0, 2000);
return `HTTP ${r.status} ${r.statusText}\ncontent-type: ${r.headers.get('content-type') || 'n/a'}\n\n${text}${text.length >= 2000 ? '\n...[truncated]' : ''}`;
} catch (e) {
return `curl: (6) ${e.message}`;
}
};
commands.geo = async function () {
if (!devMode) return 'command not found. try /help';
try {
const r = await fetch('/api/telemetry/geo');
const d = await r.json();
if (!Array.isArray(d) || !d.length) return 'GEO INTEL: no data.';
return 'GEO INTEL (24h):\n\n' + d.slice(0, 15).map((row, i) =>
` ${pad(i+1, 2)}. ${(row.country_code || 'XX').padEnd(3)} ${(row.country_name || 'Unknown').padEnd(22)} ${pad(row.count || 0, 5)}`
).join('\n');
} catch (e) {
return 'telemetry unavailable.';
}
};
// ─── Matrix rain overlay ─────────────────────────
let matrixCanvas = null;
let matrixRAF = null;
function toggleMatrix(on) {
if (on) {
matrixCanvas = document.createElement('canvas');
matrixCanvas.id = 'matrixRain';
Object.assign(matrixCanvas.style, {
position: 'fixed', inset: '0', width: '100%', height: '100%',
pointerEvents: 'none', zIndex: '7', opacity: '0.18',
});
document.body.appendChild(matrixCanvas);
const ctx = matrixCanvas.getContext('2d');
function resize() {
matrixCanvas.width = window.innerWidth;
matrixCanvas.height = window.innerHeight;
}
resize();
window.addEventListener('resize', resize);
const chars = 'アイウエオカキクケコサシスセソタチツテトナニヌネ01JAESWIFT'.split('');
const size = 16;
const cols = Math.floor(matrixCanvas.width / size);
const drops = new Array(cols).fill(1);
function draw() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.06)';
ctx.fillRect(0, 0, matrixCanvas.width, matrixCanvas.height);
ctx.fillStyle = '#00cc33';
ctx.font = size + 'px JetBrains Mono, monospace';
for (let i = 0; i < drops.length; i++) {
const ch = chars[Math.floor(Math.random() * chars.length)];
ctx.fillText(ch, i * size, drops[i] * size);
if (drops[i] * size > matrixCanvas.height && Math.random() > 0.975) drops[i] = 0;
drops[i]++;
}
matrixRAF = requestAnimationFrame(draw);
}
draw();
} else {
if (matrixRAF) cancelAnimationFrame(matrixRAF);
if (matrixCanvas) matrixCanvas.remove();
matrixCanvas = null;
}
}
// ─── Konami Code → Developer Mode ────────────────
const KONAMI = ['ArrowUp','ArrowUp','ArrowDown','ArrowDown','ArrowLeft','ArrowRight','ArrowLeft','ArrowRight','b','a'];
let kBuf = [];
document.addEventListener('keydown', function (e) {
kBuf.push(e.key);
if (kBuf.length > KONAMI.length) kBuf.shift();
const match = kBuf.length === KONAMI.length && kBuf.every((k, i) => k.toLowerCase() === KONAMI[i].toLowerCase());
if (match && !devMode) {
devMode = true;
// Add a floating dev badge
const badge = document.createElement('div');
badge.id = 'devModeBadge';
Object.assign(badge.style, {
position: 'fixed', top: '68px', right: '16px', zIndex: '900',
background: 'var(--bg-panel)', border: '1px solid var(--warning)',
color: 'var(--warning)', padding: '6px 12px', fontFamily: 'var(--font-mono)',
fontSize: '11px', letterSpacing: '1.5px', cursor: 'pointer',
boxShadow: '0 0 14px rgba(201,162,39,0.4)',
});
badge.innerHTML = '⚡ DEVELOPER MODE // UNLOCKED';
badge.title = 'Click to disable';
badge.addEventListener('click', () => {
devMode = false; badge.remove();
});
document.body.appendChild(badge);
try { window.dispatchEvent(new CustomEvent('jae-dev-mode-on')); } catch (err) {}
}
});
// ─── Entry point — handle a /-command ───────────
async function handle(raw) {
const trimmed = raw.trim();
if (!trimmed.startsWith('/')) return { handled: false };
const parts = trimmed.slice(1).split(/\s+/);
const cmd = (parts[0] || '').toLowerCase();
const args = parts.slice(1);
cmdHistory.push(trimmed);
if (cmdHistory.length > MAX_HISTORY) cmdHistory = cmdHistory.slice(-MAX_HISTORY);
saveHistory();
if (!cmd) return { handled: true, output: '' };
const fn = commands[cmd];
if (!fn) {
return { handled: true, output: `command not found: /${cmd}. type /help for available commands.` };
}
try {
const result = await fn(args);
return { handled: true, output: (result == null ? '' : String(result)) };
} catch (e) {
return { handled: true, output: `error: ${e.message}` };
}
}
window.__jaeCLI = {
handle: handle,
commands: commands,
isDev: function () { return devMode; },
};
})();

View file

@ -127,6 +127,34 @@
const text = chatInput.value.trim();
if (!text || isWaiting) return;
// ─── CLI interception ───
if (text.startsWith('/') && window.__jaeCLI && typeof window.__jaeCLI.handle === 'function') {
isWaiting = true;
chatInput.value = '';
const userBubble = addMessage('user', text);
const userMsg = userBubble && userBubble.parentElement;
if (userMsg) userMsg.classList.add('chat-msg-user-cli');
try {
const res = await window.__jaeCLI.handle(text);
if (res && res.handled) {
if (res.output) {
const body = addMessage('assistant', '');
const msgEl = body && body.parentElement;
if (msgEl) msgEl.classList.add('chat-msg-cli');
body.textContent = res.output;
chatMessages.scrollTop = chatMessages.scrollHeight;
}
}
} catch (e) {
const body = addMessage('assistant', 'cli error: ' + e.message);
const msgEl = body && body.parentElement;
if (msgEl) msgEl.classList.add('chat-msg-cli');
}
isWaiting = false;
chatInput.focus();
return;
}
isWaiting = true;
chatInput.value = '';
chatStatus.textContent = '● PROCESSING';