UNPKG

shell-mirror

Version:

Access your Mac shell from any device securely. Perfect for mobile coding with Claude Code CLI, Gemini CLI, and any shell tool.

747 lines (645 loc) 23.7 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Shell Mirror - Use Claude Code CLI and Gemini CLI from your phone</title> <meta name="description" content="Access your Mac terminal from your phone to use Claude Code CLI, Gemini CLI, and other command-line tools. Your computer, your accounts, secure access."> <meta name="keywords" content="mobile coding, remote shell, Claude Code mobile, Gemini CLI phone, Mac shell browser, secure shell sharing"> <!-- Open Graph / Facebook --> <meta property="og:type" content="website"> <meta property="og:title" content="Shell Mirror - Use Claude Code CLI and Gemini CLI from your phone"> <meta property="og:description" content="Access your Mac terminal from your phone to use Claude Code CLI, Gemini CLI, and other tools. Your computer, your accounts."> <meta property="og:url" content="https://www.igori.eu"> <!-- Twitter --> <meta property="twitter:card" content="summary_large_image"> <meta property="twitter:title" content="Shell Mirror - Use Claude Code CLI from your phone"> <meta property="twitter:description" content="Access your Mac terminal from your phone to use Claude Code CLI, Gemini CLI, and other command-line tools."> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; line-height: 1.6; color: #333; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; } .container { max-width: 1200px; margin: 0 auto; padding: 0 20px; } /* Header */ header { padding: 20px 0; position: relative; z-index: 100; } nav { display: flex; justify-content: space-between; align-items: center; } .logo { font-size: 24px; font-weight: bold; color: white; } .cta-button { background: rgba(255, 255, 255, 0.2); color: white; padding: 12px 24px; text-decoration: none; border-radius: 25px; font-weight: 500; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.3); transition: all 0.3s ease; } .cta-button:hover { background: rgba(255, 255, 255, 0.3); transform: translateY(-2px); } /* Hero Section */ .hero { text-align: center; padding: 60px 0 80px; color: white; } .hero h1 { font-size: clamp(2.5rem, 5vw, 4rem); font-weight: 700; margin-bottom: 20px; line-height: 1.2; } .hero p { font-size: clamp(1.1rem, 2vw, 1.3rem); margin-bottom: 40px; opacity: 0.9; max-width: 600px; margin-left: auto; margin-right: auto; } .hero-buttons { display: flex; gap: 20px; justify-content: center; flex-wrap: wrap; margin-bottom: 60px; } .btn-primary { background: #4285F4; color: white; padding: 16px 32px; text-decoration: none; border-radius: 30px; font-weight: 600; font-size: 1.1rem; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(66, 133, 244, 0.3); } .btn-primary:hover { background: #3367d6; transform: translateY(-2px); box-shadow: 0 6px 20px rgba(66, 133, 244, 0.4); } .btn-secondary { background: transparent; color: white; padding: 16px 32px; text-decoration: none; border-radius: 30px; font-weight: 600; font-size: 1.1rem; border: 2px solid white; transition: all 0.3s ease; } .btn-secondary:hover { background: white; color: #667eea; } /* Setup Steps */ .setup-steps { margin: 40px auto; max-width: 600px; display: flex; flex-direction: column; gap: 20px; } .setup-step { display: flex; align-items: center; gap: 20px; } .step-number { font-size: 2rem; font-weight: bold; color: white; opacity: 0.8; min-width: 40px; text-align: center; } /* Installation Code */ .install-code { background: rgba(0, 0, 0, 0.3); padding: 20px; border-radius: 15px; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); position: relative; flex: 1; height: 60px; display: flex; align-items: center; } .install-code pre { color: #00ff88; font-family: 'Monaco', 'Menlo', monospace; font-size: 1.1rem; margin: 0; padding-right: 40px; flex: 1; } .copy-btn { position: absolute; right: 15px; top: 50%; transform: translateY(-50%); background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 8px; padding: 8px; color: white; cursor: pointer; transition: all 0.2s ease; } .copy-btn:hover { background: rgba(255, 255, 255, 0.2); transform: translateY(-50%) scale(1.05); } .copy-btn:active { transform: translateY(-50%) scale(0.95); } .copy-btn svg { display: block; } /* Google Login Button */ .btn-google { background: white; color: #3c4043; padding: 20px 24px; border: 1px solid #dadce0; border-radius: 15px; font-weight: 500; font-size: 1rem; display: flex; align-items: center; justify-content: center; gap: 12px; transition: all 0.2s ease; cursor: pointer; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); flex: 1; height: 60px; } .btn-google:hover { background: #f8f9fa; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); /* transform: translateY(-1px); */ } .btn-google:active { transform: translateY(0); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); } /* Installation Modal */ .install-modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.8); z-index: 1000; align-items: center; justify-content: center; } .install-modal.show { display: flex; } .install-modal-content { background: white; padding: 30px; border-radius: 15px; max-width: 500px; margin: 20px; text-align: center; position: relative; } .install-modal-content h3 { color: #333; margin-bottom: 20px; } .install-modal-content p { color: #666; margin-bottom: 20px; } .install-modal-content .install-code { background: #f5f5f5; color: #333; margin: 20px 0; } .install-modal-content .install-code pre { color: #333; } .close-modal { position: absolute; top: 10px; right: 15px; background: none; border: none; font-size: 24px; cursor: pointer; color: #666; } .close-modal:hover { color: #000; } /* How It Works */ .how-it-works { background: white; padding: 80px 0; } .section-title { text-align: center; font-size: 2.5rem; margin-bottom: 60px; color: #333; } .steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 40px; margin-bottom: 60px; } .step { text-align: center; padding: 30px 20px; } .step-icon { width: 80px; height: 80px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 20px; font-size: 2rem; color: white; } .step h3 { font-size: 1.3rem; margin-bottom: 15px; color: #333; } .step p { color: #666; line-height: 1.6; } /* Security Section */ .security { background: #f8f9fa; padding: 80px 0; } .security-flow { display: flex; align-items: center; justify-content: center; gap: 30px; flex-wrap: wrap; margin: 40px 0; } .security-step { background: white; padding: 20px; border-radius: 15px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); text-align: center; min-width: 200px; } .security-step h4 { color: #4285F4; margin-bottom: 10px; } .arrow { font-size: 2rem; color: #4285F4; } /* Use Cases */ .use-cases { padding: 80px 0; background: white; } .use-case-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px; } .use-case { background: #f8f9fa; padding: 30px; border-radius: 15px; border-left: 4px solid #4285F4; } .use-case h3 { color: #333; margin-bottom: 15px; } .use-case p { color: #666; } /* Footer CTA */ .footer-cta { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 60px 0; text-align: center; color: white; } .footer-cta h2 { font-size: 2.5rem; margin-bottom: 20px; } .footer-cta p { font-size: 1.2rem; margin-bottom: 40px; opacity: 0.9; } /* Responsive Design */ @media (max-width: 768px) { .setup-steps { max-width: 90%; gap: 15px; } .setup-step { gap: 15px; } .step-number { font-size: 1.5rem; min-width: 30px; } .install-code { height: 50px; padding: 15px; } .btn-google { height: 50px; padding: 15px 20px; font-size: 0.9rem; } .hero-buttons { flex-direction: column; align-items: center; } .btn-primary { width: 250px; } .security-flow { flex-direction: column; } .arrow { transform: rotate(90deg); } .steps { grid-template-columns: 1fr; } } /* Animations */ @keyframes fadeInUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } .hero, .step, .use-case { animation: fadeInUp 0.6s ease-out; } </style> </head> <body> <header> <nav class="container"> <div class="logo">Shell Mirror</div> <a href="/app" class="cta-button">Launch App</a> </nav> </header> <main> <!-- Hero Section --> <section class="hero"> <div class="container"> <h1>Access your Mac terminal<br>from anywhere</h1> <p>Cloud-based terminal access for your Mac. Use Claude Code CLI, Gemini CLI, and other command-line tools from your phone or any device.</p> <div class="hero-buttons"> <button class="btn-primary" onclick="handleGoogleLogin()"> <svg width="20" height="20" viewBox="0 0 24 24" style="margin-right: 8px;"> <path fill="white" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/> <path fill="white" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/> <path fill="white" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/> <path fill="white" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/> </svg> Start with Google </button> <a href="#how-it-works" class="btn-secondary">Learn More</a> </div> </div> </section> <!-- How It Works --> <section class="how-it-works" id="how-it-works"> <div class="container"> <h2 class="section-title">How Shell Mirror Works</h2> <div class="steps"> <div class="step"> <div class="step-icon">🔐</div> <h3>Secure Login</h3> <p>Sign in with your Google account. Your credentials are encrypted and secure.</p> </div> <div class="step"> <div class="step-icon">🌐</div> <h3>Cloud Terminal</h3> <p>Access a cloud-based terminal environment with all your favorite command-line tools pre-installed.</p> </div> <div class="step"> <div class="step-icon">📱</div> <h3>Any Device</h3> <p>Use from your phone, tablet, or any web browser. Your terminal is always accessible.</p> </div> </div> </div> </section> <!-- Security --> <section class="security" id="security"> <div class="container"> <h2 class="section-title">Secure & Reliable</h2> <p style="text-align: center; margin-bottom: 40px; color: #666; font-size: 1.1rem;"> Enterprise-grade security with Google OAuth authentication. </p> <div class="security-flow"> <div class="security-step"> <h4>Your Device</h4> <p>Any web browser</p> </div> <div class="arrow"></div> <div class="security-step"> <h4>Secure Login</h4> <p>Google OAuth 2.0</p> </div> <div class="arrow"></div> <div class="security-step"> <h4>Cloud Terminal</h4> <p>Instant access</p> </div> </div> <div style="text-align: center; margin-top: 40px;"> <p style="color: #666;">✅ Encrypted connections (HTTPS/WSS)<br> ✅ Google-grade authentication<br> ✅ Session-based security<br> ✅ No local installation required</p> </div> </div> </section> <!-- Use Cases --> <section class="use-cases" id="use-cases"> <div class="container"> <h2 class="section-title">Use Cases</h2> <div class="use-case-grid"> <div class="use-case"> <h3>🤖 Claude Code CLI</h3> <p>Use Claude Code CLI from your phone. Run AI-powered coding commands using your own Claude API account.</p> </div> <div class="use-case"> <h3>✨ Gemini CLI</h3> <p>Use Gemini CLI from your phone. Access Google's AI tools with your own Google account and API access.</p> </div> <div class="use-case"> <h3>🔧 Standard Tools</h3> <p>Git, npm, pip, Docker, SSH - all your usual command-line tools work normally from your phone.</p> </div> <div class="use-case"> <h3>🔧 Quick Fixes</h3> <p>Fix bugs, check logs, or deploy code from your phone. Full access to your development environment.</p> </div> <div class="use-case"> <h3>📱 Mobile Development</h3> <p>Code during commutes or away from your desk. Follow tutorials and practice programming from your phone.</p> </div> <div class="use-case"> <h3>🏠 Personal Projects</h3> <p>Work on personal projects from anywhere. Your own computer, your own accounts, your own code.</p> </div> </div> </div> </section> <!-- Footer CTA --> <section class="footer-cta" id="get-started"> <div class="container"> <h2>Ready to Start?</h2> <p>Access your terminal from anywhere in seconds</p> <div style="margin-top: 40px;"> <button class="btn-primary" onclick="handleGoogleLogin()" style="margin-right: 20px; padding: 20px 40px; font-size: 1.2rem;">Start Now</button> <a href="https://github.com/karmalsky/shell-mirror" class="btn-secondary">View on GitHub</a> </div> <p style="margin-top: 30px; opacity: 0.8; font-size: 0.9rem;"> Free to use • Secure • No installation required </p> </div> </section> <!-- Version Footer --> <footer style="background: #1a1a1a; color: #666; text-align: center; padding: 20px 0; font-size: 0.8rem;"> <div class="container"> <p id="version-info">Shell Mirror v1.5.2 • Loading build info...</p> </div> </footer> </main> <script> // Check if user is already authenticated and redirect to terminal async function checkAuthAndRedirect() { try { const response = await fetch('/php-backend/api/auth-status.php'); const data = await response.json(); if (data.success && data.data && data.data.authenticated) { // User is logged in, redirect to terminal window.location.href = '/app/terminal.html'; return true; } } catch (error) { console.log('Auth check failed:', error); } return false; } // Handle Google login - direct web OAuth async function handleGoogleLogin() { // Check if already logged in first const isLoggedIn = await checkAuthAndRedirect(); if (isLoggedIn) return; // Direct OAuth flow using the web backend window.location.href = '/php-backend/api/auth-login.php'; } // Load version info async function loadVersionInfo() { try { const response = await fetch('/build-info.json'); const buildInfo = await response.json(); const versionElement = document.getElementById('version-info'); if (versionElement && buildInfo) { const buildDate = new Date(buildInfo.buildTime).toLocaleDateString(); versionElement.textContent = `Shell Mirror v${buildInfo.version} • Built ${buildDate}`; } } catch (error) { console.log('Could not load build info:', error); } } // Check authentication status on page load document.addEventListener('DOMContentLoaded', () => { checkAuthAndRedirect(); loadVersionInfo(); }); // Smooth scrolling for anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); document.querySelector(this.getAttribute('href')).scrollIntoView({ behavior: 'smooth' }); }); }); // Add intersection observer for animations const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; } }); }, observerOptions); // Observe elements for animation document.querySelectorAll('.step, .use-case').forEach(el => { el.style.opacity = '0'; el.style.transform = 'translateY(30px)'; el.style.transition = 'opacity 0.6s ease, transform 0.6s ease'; observer.observe(el); }); </script> </body> </html>