<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>yaak — think it, run it</title>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400;1,700&family=DM+Mono:wght@300;400;500&family=Source+Serif+4:ital,opsz,wght@0,8..60,300;0,8..60,400;0,8..60,600;1,8..60,300;1,8..60,400&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<style>
/* ============ HERO ============ */
.hero {
padding: 100px 32px 80px;
position: relative;
}
.hero-kicker {
font-family: 'DM Mono', monospace;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 3px;
color: var(--red);
margin-bottom: 24px;
animation: fadeIn 0.6s ease both;
}
.hero-headline {
font-family: 'Playfair Display', serif;
font-weight: 900;
font-size: clamp(52px, 9vw, 120px);
line-height: 0.92;
letter-spacing: -3px;
max-width: 900px;
margin-bottom: 40px;
animation: fadeIn 0.6s ease 0.1s both;
}
.hero-headline em {
font-style: italic;
font-weight: 400;
color: var(--red);
}
.hero-row {
display: grid;
grid-template-columns: 1fr 1px 1fr;
gap: 48px;
align-items: start;
animation: fadeIn 0.6s ease 0.2s both;
}
.hero-divider {
width: 1px;
height: 100%;
min-height: 120px;
background: var(--rule);
}
.hero-lede {
font-size: 19px;
line-height: 1.65;
color: var(--ink-light);
font-weight: 300;
max-width: 420px;
}
.hero-lede strong {
font-weight: 600;
color: var(--ink);
}
.hero-install-area {
display: flex;
flex-direction: column;
gap: 16px;
}
.install-label {
font-family: 'DM Mono', monospace;
font-size: 10px;
text-transform: uppercase;
letter-spacing: 2px;
color: var(--ink-dim);
}
.install-cmd {
font-family: 'DM Mono', monospace;
font-size: 14px;
background: var(--code-bg);
color: var(--code-fg);
padding: 16px 20px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
transition: transform 0.15s;
gap: 12px;
}
.install-cmd:hover { transform: translateY(-1px); }
.install-cmd .prompt { color: var(--code-green); margin-right: 8px; }
.install-cmd .copy-btn {
font-family: 'DM Mono', monospace;
font-size: 9px;
text-transform: uppercase;
letter-spacing: 1.5px;
color: var(--ink-faint);
background: none;
border: 1px solid #333;
padding: 4px 10px;
border-radius: 3px;
cursor: pointer;
transition: all 0.2s;
white-space: nowrap;
}
.install-cmd .copy-btn:hover { border-color: var(--code-green); color: var(--code-green); }
.hero-rule {
border: none;
border-top: 3px double var(--rule);
margin-top: 80px;
}
/* ============ TERMINAL DEMO ============ */
.demo-section {
padding: 60px 32px 80px;
}
.demo-columns {
display: grid;
grid-template-columns: 280px 1fr;
gap: 48px;
align-items: start;
}
.demo-aside {
position: sticky;
top: 100px;
}
.demo-aside h2 {
font-family: 'Playfair Display', serif;
font-size: 32px;
font-weight: 900;
line-height: 1.15;
letter-spacing: -0.5px;
margin-bottom: 16px;
}
.demo-aside p {
font-size: 14px;
line-height: 1.7;
color: var(--ink-dim);
font-weight: 300;
}
.terminal {
background: var(--code-bg);
border-radius: 10px;
overflow: hidden;
width: 640px;
max-width: 100%;
box-shadow:
0 25px 60px rgba(26, 22, 21, 0.2),
0 2px 4px rgba(26, 22, 21, 0.1);
}
.terminal-bar {
display: flex;
align-items: center;
gap: 7px;
padding: 14px 18px;
background: rgba(255,255,255,0.04);
border-bottom: 1px solid rgba(255,255,255,0.06);
}
.terminal-dot { width: 10px; height: 10px; border-radius: 50%; }
.terminal-dot:nth-child(1) { background: #e25d52; }
.terminal-dot:nth-child(2) { background: #e6a73a; }
.terminal-dot:nth-child(3) { background: #58c142; }
.terminal-title {
flex: 1;
text-align: center;
font-family: 'DM Mono', monospace;
font-size: 11px;
color: #666;
}
.terminal-body {
padding: 24px;
font-family: 'DM Mono', monospace;
font-size: 13px;
line-height: 1.9;
height: 480px;
overflow-y: auto;
color: var(--code-fg);
}
.t-green { color: var(--code-green); }
.t-amber { color: var(--code-amber); }
.t-dim { color: #777; }
.t-bold { font-weight: 500; color: #fff; }
.t-red { color: var(--red-light); }
.t-cyan { color: #6ec2d6; }
.terminal-line {
opacity: 0;
animation: lineIn 0.35s ease forwards;
}
@keyframes lineIn {
from { opacity: 0; transform: translateY(3px); }
to { opacity: 1; transform: translateY(0); }
}
.cursor-blink {
display: inline-block;
width: 7px; height: 15px;
background: var(--code-green);
vertical-align: middle;
animation: blink 1s step-end infinite;
}
@keyframes blink { 50% { opacity: 0; } }
/* ============ WHY ============ */
.why-section {
padding: 40px 32px 80px;
border-top: 1px solid var(--rule);
}
.section-header {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 48px;
margin-bottom: 64px;
align-items: end;
}
.section-number {
font-family: 'Playfair Display', serif;
font-size: 160px;
font-weight: 900;
line-height: 0.8;
color: var(--paper-dark);
letter-spacing: -8px;
user-select: none;
}
.section-header-text h2 {
font-family: 'Playfair Display', serif;
font-size: clamp(32px, 4.5vw, 48px);
font-weight: 900;
line-height: 1.1;
letter-spacing: -1px;
margin-bottom: 12px;
}
.section-header-text h2 em {
font-style: italic;
font-weight: 400;
color: var(--red);
}
.section-header-text p {
font-size: 15px;
line-height: 1.65;
color: var(--ink-dim);
font-weight: 300;
max-width: 440px;
}
.why-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
border-top: 1px solid var(--rule);
border-left: 1px solid var(--rule);
}
.why-cell {
padding: 36px 28px;
border-right: 1px solid var(--rule);
border-bottom: 1px solid var(--rule);
transition: background 0.3s;
position: relative;
}
.why-cell:hover {
background: var(--cream);
}
.why-cell .cell-number {
font-family: 'Playfair Display', serif;
font-size: 42px;
font-weight: 900;
color: var(--paper-dark);
position: absolute;
top: 12px;
right: 16px;
line-height: 1;
}
.why-cell h3 {
font-family: 'Playfair Display', serif;
font-size: 18px;
font-weight: 700;
margin-bottom: 10px;
letter-spacing: -0.3px;
}
.why-cell p {
font-size: 13px;
line-height: 1.7;
color: var(--ink-dim);
font-weight: 300;
}
.why-cell code {
font-family: 'DM Mono', monospace;
font-size: 12px;
background: var(--code-bg);
color: var(--code-green);
padding: 1px 6px;
border-radius: 3px;
}
/* ============ HOW IT WORKS ============ */
.how-section {
padding: 60px 32px 100px;
border-top: 1px solid var(--rule);
}
.steps {
display: flex;
flex-direction: column;
gap: 0;
}
.step {
display: grid;
grid-template-columns: 160px 1fr 1fr;
gap: 0;
border-bottom: 1px solid var(--rule);
min-height: 180px;
}
.step-label {
padding: 32px 24px;
border-right: 1px solid var(--rule);
display: flex;
flex-direction: column;
gap: 8px;
}
.step-num {
font-family: 'Playfair Display', serif;
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 2px;
color: var(--red);
}
.step-name {
font-family: 'Playfair Display', serif;
font-size: 28px;
font-weight: 900;
letter-spacing: -0.5px;
}
.step-desc {
padding: 32px 28px;
border-right: 1px solid var(--rule);
font-size: 14px;
line-height: 1.7;
color: var(--ink-dim);
font-weight: 300;
display: flex;
align-items: center;
}
.step-code-area {
padding: 24px;
display: flex;
align-items: center;
}
.step-code {
width: 100%;
font-family: 'DM Mono', monospace;
font-size: 12px;
background: var(--code-bg);
color: var(--code-fg);
padding: 16px 18px;
border-radius: 6px;
line-height: 1.8;
overflow-x: auto;
}
/* ============ PROVIDERS ============ */
.providers-section {
padding: 60px 32px 80px;
border-top: 1px solid var(--rule);
text-align: center;
}
.providers-title {
font-family: 'Playfair Display', serif;
font-size: clamp(28px, 4vw, 40px);
font-weight: 900;
letter-spacing: -0.5px;
margin-bottom: 12px;
}
.providers-title em { font-style: italic; font-weight: 400; color: var(--red); }
.providers-sub {
font-size: 14px;
color: var(--ink-dim);
font-weight: 300;
margin-bottom: 48px;
}
.provider-row {
display: flex;
flex-wrap: wrap;
gap: 12px;
justify-content: center;
max-width: 700px;
margin: 0 auto;
}
.provider-tag {
font-family: 'DM Mono', monospace;
font-size: 12px;
padding: 10px 20px;
border: 1px solid var(--rule);
border-radius: 100px;
color: var(--ink-light);
transition: all 0.25s;
cursor: default;
background: var(--cream);
}
.provider-tag:hover {
border-color: var(--red);
color: var(--red);
background: white;
}
/* ============ CTA ============ */
.cta-section {
padding: 80px 32px 100px;
border-top: 3px double var(--rule);
text-align: center;
}
.cta-ornament {
font-family: 'Playfair Display', serif;
font-size: 40px;
color: var(--rule);
margin-bottom: 32px;
user-select: none;
}
.cta-headline {
font-family: 'Playfair Display', serif;
font-size: clamp(36px, 5vw, 56px);
font-weight: 900;
line-height: 1.05;
letter-spacing: -1.5px;
margin-bottom: 20px;
}
.cta-headline em { font-style: italic; font-weight: 400; color: var(--red); }
.cta-body {
font-size: 15px;
line-height: 1.7;
color: var(--ink-dim);
font-weight: 300;
max-width: 420px;
margin: 0 auto 40px;
}
.cta-button {
display: inline-flex;
align-items: center;
gap: 10px;
font-family: 'DM Mono', monospace;
font-size: 14px;
background: var(--red);
color: white;
border: none;
padding: 16px 32px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
text-decoration: none;
}
.cta-button:hover {
background: var(--ink);
transform: translateY(-1px);
box-shadow: 0 8px 24px rgba(26, 22, 21, 0.15);
}
.cta-alt {
margin-top: 20px;
font-size: 13px;
color: var(--ink-faint);
font-family: 'DM Mono', monospace;
letter-spacing: 0.5px;
}
.cta-button--secondary {
display: inline-flex;
margin-top: 10px;
background: transparent;
color: var(--ink-dim);
border: 1px solid var(--rule);
font-size: 13px;
padding: 12px 24px;
}
.cta-button--secondary:hover {
background: var(--ink);
color: white;
border-color: var(--ink);
}
.reveal {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.reveal.visible { opacity: 1; transform: translateY(0); }
/* ============ RESPONSIVE ============ */
@media (max-width: 768px) {
.hero { padding: 60px 16px 60px; }
.container { padding: 0 16px; }
.hero-row { grid-template-columns: 1fr; gap: 32px; }
.hero-divider { display: none; }
.install-cmd { font-size: 11px; padding: 12px 14px; overflow-x: auto; white-space: nowrap; }
.demo-section { padding: 40px 16px 60px; }
.demo-columns { grid-template-columns: 1fr; }
.demo-aside { position: static; }
.terminal { width: 100%; min-width: 0; }
.terminal-body { padding: 16px; font-size: 11px; height: 360px; overflow-x: auto; word-break: break-all; }
.terminal-line { white-space: pre-wrap; word-break: break-all; }
.section-header { grid-template-columns: 1fr; gap: 16px; }
.section-number { font-size: 80px; letter-spacing: -4px; }
.why-section { padding: 40px 16px 60px; }
.why-grid { grid-template-columns: 1fr; }
.how-section { padding: 40px 16px 60px; }
.step { grid-template-columns: 1fr; }
.step-label { border-right: none; border-bottom: 1px solid var(--rule); padding: 20px 16px; }
.step-desc { border-right: none; padding: 20px 16px; }
.step-code-area { padding: 0 16px 20px; }
.step-code { font-size: 11px; overflow-x: auto; }
.providers-section { padding: 40px 16px 60px; }
.provider-tag { font-size: 11px; padding: 8px 14px; }
.cta-section { padding: 60px 16px 80px; }
}
</style>
</head>
<body>
<!-- NAV -->
<nav>
<a href="#" class="nav-brand">yaak</a>
<button class="hamburger" id="hamburger" aria-label="Open menu" aria-expanded="false">
<span></span><span></span><span></span>
</button>
<div class="nav-right">
<a href="#why">Why</a>
<a href="#how">How it works</a>
<a href="#providers">Providers</a>
<a href="docs.html">Docs</a>
<a href="examples.html">Examples</a>
<a href="blog.html">Blog</a>
<a href="changelog.html">Changelog</a>
<a href="https://github.com/hanneshapke/yaak" class="nav-gh">
<svg width="14" height="14" fill="currentColor" viewBox="0 0 16 16"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
Star on GitHub
</a>
</div>
</nav>
<!-- MOBILE MENU OVERLAY -->
<div class="mobile-menu" id="mobileMenu">
<a href="#why" class="mobile-menu-link">Why</a>
<a href="#how" class="mobile-menu-link">How it works</a>
<a href="#providers" class="mobile-menu-link">Providers</a>
<a href="docs.html" class="mobile-menu-link">Docs</a>
<a href="examples.html" class="mobile-menu-link">Examples</a>
<a href="blog.html" class="mobile-menu-link">Blog</a>
<a href="changelog.html" class="mobile-menu-link">Changelog</a>
<a href="https://github.com/hanneshapke/yaak" class="mobile-menu-link nav-gh">
<svg width="14" height="14" fill="currentColor" viewBox="0 0 16 16"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
Star on GitHub
</a>
</div>
<!-- HERO -->
<section class="hero">
<div class="container">
<div class="hero-kicker">A command-line companion</div>
<h1 class="hero-headline">
Stop googling<br>bash <em>syntax.</em>
</h1>
<div class="hero-row">
<div class="hero-lede">
<strong>yaak</strong> (<em>Yet Another AI for the Kommandozeile</em>) is a tiny Rust CLI that translates natural language
into the right shell command — using Anthropic, Google Gemini, OpenAI, or any compatible model you choose.
Supports 8 languages. Describe what you want, review the command, hit enter. That's it.
</div>
<div class="hero-divider"></div>
<div class="hero-install-area">
<div class="install-label">Quick install (macOS / Linux)</div>
<div class="install-cmd" onclick="copyCmd(this, 'curl -fsSL https://getyaak.ai/install.sh | bash')">
<span><span class="prompt">$</span> curl -fsSL https://getyaak.ai/install.sh | bash</span>
<button class="copy-btn">Copy</button>
</div>
<div class="install-label" style="margin-top: 12px;">Or via Homebrew</div>
<div class="install-cmd" onclick="copyCmd(this, 'brew install hanneshapke/yaak/yaak')">
<span><span class="prompt">$</span> brew install hanneshapke/yaak/yaak</span>
<button class="copy-btn">Copy</button>
</div>
<div style="font-size:12px; color:var(--ink-faint); font-family:'DM Mono',monospace; letter-spacing:0.5px; margin-top: 10px;">
Also on <a href="docs.html#install" style="color:var(--ink-faint); text-decoration: underline;">AUR</a>,
<a href="docs.html#install" style="color:var(--ink-faint); text-decoration: underline;">Nix</a>,
<a href="docs.html#install" style="color:var(--ink-faint); text-decoration: underline;">.deb</a> and
<a href="docs.html#install" style="color:var(--ink-faint); text-decoration: underline;">Scoop</a>.
</div>
<div style="font-size:12px; color:var(--ink-faint); font-family:'DM Mono',monospace; letter-spacing:0.5px;">
Set YAAK_API_KEY and go.
</div>
</div>
</div>
<hr class="hero-rule">
</div>
</section>
<!-- DEMO -->
<section class="demo-section">
<div class="container">
<div class="demo-columns">
<div class="demo-aside reveal">
<h2>See it in action</h2>
<p>Real examples cycling below. yaak handles compression, file search, process management, clipboard copy — anything you can describe.</p>
</div>
<div class="terminal reveal" id="terminal-demo">
<div class="terminal-bar">
<div class="terminal-dot"></div>
<div class="terminal-dot"></div>
<div class="terminal-dot"></div>
<span class="terminal-title">~/projects</span>
</div>
<div class="terminal-body" id="terminal-body"></div>
</div>
</div>
</div>
</section>
<!-- WHY -->
<section class="why-section" id="why">
<div class="container">
<div class="section-header reveal">
<div class="section-number">01</div>
<div class="section-header-text">
<h2>Your brain knows <em>what</em>.<br>Let yaak know <em>how</em>.</h2>
<p>Six reasons developers are replacing their Stack Overflow tab with a four-letter command.</p>
</div>
</div>
<div class="why-grid reveal">
<div class="why-cell">
<span class="cell-number">i</span>
<h3>Faster than searching</h3>
<p>No more context-switching to a browser, skimming Stack Overflow, and copy-pasting flags you don't understand. Just say what you need.</p>
</div>
<div class="why-cell">
<span class="cell-number">ii</span>
<h3>You stay in control</h3>
<p>Every generated command is shown before execution. Nothing runs until you confirm. Pass <code>-y</code> when you trust it.</p>
</div>
<div class="why-cell">
<span class="cell-number">iii</span>
<h3>Bring your own model</h3>
<p>Works with Anthropic, Google Gemini, OpenAI, Ollama, Groq, Together, OpenRouter, Doubleword, or any local server. You own the key and pick the model.</p>
</div>
<div class="why-cell">
<span class="cell-number">iv</span>
<h3>Context-aware</h3>
<p>Pass <code>--context</code> and yaak detects your project type (Cargo, npm, Go, Docker, etc.), git branch, and files — so "build the project" just works.</p>
</div>
<div class="why-cell">
<span class="cell-number">v</span>
<h3>Copy, cache & recall</h3>
<p>Copy to clipboard with <code>-C</code>, cache results with <code>--cache</code> (exact or BM25 fuzzy match), browse history with <code>--history</code>, re-run with <code>--last</code>, or search with <code>--search</code>.</p>
</div>
<div class="why-cell">
<span class="cell-number">vi</span>
<h3>8 languages</h3>
<p>Use yaak in English, Deutsch, Español, Français, Português, 中文, 日本語, or 한국어. Set once with <code>--language</code> or auto-detect from your system locale.</p>
</div>
</div>
</div>
</section>
<!-- HOW IT WORKS -->
<section class="how-section" id="how">
<div class="container">
<div class="section-header reveal">
<div class="section-number">02</div>
<div class="section-header-text">
<h2>Three seconds from<br><em>thought</em> to <em>execution</em>.</h2>
<p>The simplest workflow in the terminal. No configuration files, no learning curve, no magic.</p>
</div>
</div>
<div class="steps reveal">
<div class="step">
<div class="step-label">
<div class="step-num">Step I</div>
<div class="step-name">Describe</div>
</div>
<div class="step-desc">
Type what you want in any supported language after the yaak command. No quoting needed — trailing arguments are joined automatically.
</div>
<div class="step-code-area">
<div class="step-code">
<span class="t-green">$</span> yaak <span class="t-dim">find all rust files modified this week</span>
</div>
</div>
</div>
<div class="step">
<div class="step-label">
<div class="step-num">Step II</div>
<div class="step-name">Review</div>
</div>
<div class="step-desc">
yaak streams the response from your LLM and displays the generated command. Nothing runs until you choose — execute, copy to clipboard, or abort.
</div>
<div class="step-code-area">
<div class="step-code">
<span class="t-dim"> Command:</span> <span class="t-green">find . -name "*.rs" -mtime -7</span><br>
<span class="t-amber">? What next?:</span> <span class="t-bold">Execute</span> / Refine / Copy / Abort
</div>
</div>
</div>
<div class="step">
<div class="step-label">
<div class="step-num">Step III</div>
<div class="step-name">Run</div>
</div>
<div class="step-desc">
Hit enter. The command runs in your shell with your permissions. yaak exits with the same code as the command it ran.
</div>
<div class="step-code-area">
<div class="step-code">
<span class="t-dim">./src/main.rs</span><br>
<span class="t-dim">./src/lib.rs</span><br>
<span class="t-dim">./tests/integration.rs</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- PROVIDERS -->
<section class="providers-section" id="providers">
<div class="container">
<div class="reveal">
<div class="providers-title">Works with <em>every</em> provider.</div>
<p class="providers-sub">Native support for Anthropic and Google Gemini, plus any endpoint that speaks the OpenAI chat completions protocol.</p>
</div>
<div class="provider-row reveal">
<span class="provider-tag">Anthropic</span>
<span class="provider-tag">Google Gemini</span>
<span class="provider-tag">OpenAI</span>
<span class="provider-tag">Ollama</span>
<span class="provider-tag">Groq</span>
<span class="provider-tag">Together AI</span>
<span class="provider-tag">OpenRouter</span>
<span class="provider-tag">Doubleword</span>
<span class="provider-tag">vLLM</span>
<span class="provider-tag">LM Studio</span>
<span class="provider-tag">LocalAI</span>
</div>
</div>
</section>
<!-- CTA -->
<section class="cta-section">
<div class="container">
<div class="reveal">
<div class="cta-ornament">✽</div>
<h2 class="cta-headline">Stop searching.<br>Start <em>yaaking.</em></h2>
<p class="cta-body">One curl command. One environment variable. Then just describe what you want.</p>
<button class="cta-button" onclick="copyCmd(this, 'curl -fsSL https://getyaak.ai/install.sh | bash')">
$ curl -fsSL https://getyaak.ai/install.sh | bash
</button>
<div class="cta-alt">
or via Homebrew:
<button class="cta-button cta-button--secondary" onclick="copyCmd(this, 'brew install hanneshapke/yaak/yaak')">
$ brew install hanneshapke/yaak/yaak
</button>
</div>
</div>
</div>
</section>
<!-- FOOTER -->
<footer>
<span>yaak — open source, Apache-2.0 licensed</span>
<span>Built with Rust & <a href="#">your favorite LLM</a></span>
</footer>
<script>
// Hamburger menu toggle
const hamburger = document.getElementById('hamburger');
const mobileMenu = document.getElementById('mobileMenu');
hamburger.addEventListener('click', () => {
const isOpen = mobileMenu.classList.toggle('open');
hamburger.classList.toggle('active');
hamburger.setAttribute('aria-expanded', isOpen);
document.body.style.overflow = isOpen ? 'hidden' : '';
});
// Close mobile menu when a link is clicked
mobileMenu.querySelectorAll('.mobile-menu-link').forEach(link => {
link.addEventListener('click', () => {
mobileMenu.classList.remove('open');
hamburger.classList.remove('active');
hamburger.setAttribute('aria-expanded', 'false');
document.body.style.overflow = '';
});
});
function copyCmd(el, cmd) {
navigator.clipboard.writeText(cmd || 'cargo install yaak');
const btn = el.querySelector('.copy-btn') || el;
const orig = btn.textContent;
btn.textContent = 'Copied!';
setTimeout(() => { btn.textContent = orig; }, 1400);
}
// Terminal animation
const demos = [
{
lines: [
{ text: '<span class="t-green">$</span> <span class="t-bold">yaak --config</span>', delay: 800 },
{ text: '<span class="t-bold">yaak configuration wizard</span>', delay: 600 },
{ text: '<span class="t-dim">────────────────────────────────────────</span>', delay: 400 },
{ text: '', delay: 200 },
{ text: '<span class="t-amber">? Select your language:</span>', delay: 600 },
{ text: ' <span class="t-dim">1.</span> English', delay: 150 },
{ text: ' <span class="t-dim">2.</span> Deutsch', delay: 150 },
{ text: '<span class="t-green">❯ 3.</span> <span class="t-bold">Español</span>', delay: 150 },
{ text: ' <span class="t-dim">4.</span> Français <span class="t-dim">5.</span> Português <span class="t-dim">6.</span> 中文 <span class="t-dim">7.</span> 日本語 <span class="t-dim">8.</span> 한국어', delay: 300 },
{ text: '', delay: 600 },
{ text: '<span class="t-amber">? Selecciona tu proveedor de API:</span>', delay: 600 },
{ text: '<span class="t-green">❯ 1.</span> <span class="t-bold">Ollama</span>', delay: 400 },
{ text: '', delay: 600 },
{ text: '<span class="t-amber">? Selecciona un modelo:</span> <span class="t-green">gemma4:e2b</span>', delay: 1000 },
{ text: '', delay: 400 },
{ text: '<span class="t-dim">────────────────────────────────────────</span>', delay: 400 },
{ text: '<span class="t-green">✓</span> <span class="t-bold">Configuración guardada en ~/.config/yaak/config.toml</span>', delay: 800 },
{ text: '', delay: 400 },
{ text: '<span class="t-green">¡Listo! Prueba: yaak listar archivos en el directorio actual</span>', delay: 800 },
]
},
{
lines: [
{ text: '<span class="t-green">$</span> <span class="t-bold">yaak</span> <span class="t-dim">compress all png files in this directory</span>', delay: 600 },
{ text: '<span class="t-dim">Thinking...</span>', delay: 1000, replace: true },
{ text: '<span class="t-dim"> Command:</span> <span class="t-green">find . -maxdepth 1 -name "*.png" -exec pngquant --force --ext .png {} \\;</span>', delay: 1800 },
{ text: '<span class="t-amber">? What next?:</span> <span class="t-bold">Execute</span> <span class="t-dim">/ Refine / Copy / Abort</span>', delay: 1200 },
{ text: '<span class="t-dim"> compressed 14 files, saved 2.3 MB</span>', delay: 1000 },
]
},
{
lines: [
{ text: '<span class="t-green">$</span> <span class="t-bold">yaak</span> <span class="t-dim">show the 5 largest files in this repo</span>', delay: 600 },
{ text: '<span class="t-dim">Thinking...</span>', delay: 1000, replace: true },
{ text: '<span class="t-dim"> Command:</span> <span class="t-green">find . -type f -exec du -h {} + | sort -rh | head -5</span>', delay: 1800 },
{ text: '<span class="t-amber">? What next?:</span> <span class="t-bold">Execute</span> <span class="t-dim">/ Refine / Copy / Abort</span>', delay: 1200 },
{ text: '<span class="t-dim"> 12M ./assets/demo.mp4</span>', delay: 400 },
{ text: '<span class="t-dim"> 4.2M ./target/release/yaak</span>', delay: 300 },
{ text: '<span class="t-dim"> 1.1M ./docs/screenshot.png</span>', delay: 300 },
]
},
{
lines: [
{ text: '<span class="t-green">$</span> <span class="t-bold">yaak</span> <span class="t-dim">kill whatever is using port 3000</span>', delay: 600 },
{ text: '<span class="t-dim">Thinking...</span>', delay: 1000, replace: true },
{ text: '<span class="t-dim"> Command:</span> <span class="t-green">lsof -ti:3000 | xargs kill -9</span>', delay: 1800 },
{ text: '<span class="t-amber">? What next?:</span> <span class="t-bold">Execute</span> <span class="t-dim">/ Refine / Copy / Abort</span>', delay: 1200 },
{ text: '<span class="t-green">$</span> <span class="cursor-blink"></span>', delay: 800 },
]
},
{
lines: [
{ text: '<span class="t-green">$</span> <span class="t-bold">yaak --reverse</span> <span class="t-dim">find . -name "*.log" -mtime +30 -delete</span>', delay: 600 },
{ text: '<span class="t-dim">Explaining...</span>', delay: 1000, replace: true },
{ text: '<span class="t-dim">────────────────────────────────────────────</span>', delay: 800 },
{ text: ' <span class="t-bold">💡 Delete all .log files older than 30 days.</span>', delay: 800 },
{ text: '', delay: 400 },
{ text: ' <span class="t-cyan" style="text-decoration:underline">BREAKDOWN</span>', delay: 600 },
{ text: ' <span class="t-dim">│</span> <span class="t-green">find</span> <span class="t-dim">→</span> Search for files and directories', delay: 400 },
{ text: ' <span class="t-dim">│</span> <span class="t-green">.</span> <span class="t-dim">→</span> Start from current directory', delay: 300 },
{ text: ' <span class="t-dim">│</span> <span class="t-green">-name "*.log"</span> <span class="t-dim">→</span> Match files ending in .log', delay: 300 },
{ text: ' <span class="t-dim">│</span> <span class="t-green">-mtime +30</span> <span class="t-dim">→</span> Only those modified 30+ days ago', delay: 300 },
{ text: ' <span class="t-dim">│</span> <span class="t-green">-delete</span> <span class="t-dim">→</span> Remove each matched file', delay: 300 },
{ text: '', delay: 400 },
{ text: ' <span class="t-amber">⚠ CAUTION:</span> <span class="t-amber">-delete is permanent — no trash, no undo.</span>', delay: 800 },
{ text: '<span class="t-dim">────────────────────────────────────────────</span>', delay: 600 },
]
}
];
let demoIdx = 0;
const sleep = ms => new Promise(r => setTimeout(r, ms));
async function playDemo(demo) {
const body = document.getElementById('terminal-body');
body.innerHTML = '';
let replaceTarget = null;
for (const step of demo.lines) {
await sleep(step.delay || 300);
if (step.replace) {
// This line will be replaced by the next one
const placeholder = document.createElement('div');
placeholder.className = 'terminal-line';
placeholder.innerHTML = step.text;
body.appendChild(placeholder);
replaceTarget = placeholder;
continue;
}
if (replaceTarget) {
replaceTarget.innerHTML = step.text;
replaceTarget = null;
continue;
}
const div = document.createElement('div');
div.className = 'terminal-line';
div.innerHTML = step.text;
body.appendChild(div);
}
await sleep(2800);
demoIdx = (demoIdx + 1) % demos.length;
playDemo(demos[demoIdx]);
}
const tObs = new IntersectionObserver(entries => {
entries.forEach(e => {
if (e.isIntersecting) { playDemo(demos[0]); tObs.disconnect(); }
});
}, { threshold: 0.3 });
tObs.observe(document.getElementById('terminal-demo'));
// Scroll reveal
const rObs = new IntersectionObserver(entries => {
entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('visible'); });
}, { threshold: 0.08, rootMargin: '0px 0px -30px 0px' });
document.querySelectorAll('.reveal').forEach(el => rObs.observe(el));
</script>
</body>
</html>