aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-04-07 13:16:59 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-04-07 13:16:59 +0300
commitfd89da606eed8c539181e0ba7a144271adebaba5 (patch)
treebfd5498d63463759fa0b71b7501c089e8ee693ac
parentc76b0b26b8529f2a35dfc4258a460b8568b99c84 (diff)
feat: add website update manifest
-rw-r--r--website/_headers19
-rw-r--r--website/_redirects1
-rw-r--r--website/assets/demo.mp4bin0 -> 3679439 bytes
-rw-r--r--website/assets/hero-screenshot.pngbin0 -> 241383 bytes
-rw-r--r--website/assets/logo.pngbin0 -> 120644 bytes
-rw-r--r--website/assets/og-card.pngbin0 -> 139994 bytes
-rw-r--r--website/assets/sidebar-agents.pngbin0 -> 5900 bytes
-rw-r--r--website/assets/sidebar-workspaces.pngbin0 -> 5344 bytes
-rw-r--r--website/index.html978
-rwxr-xr-xwebsite/install.sh88
-rw-r--r--website/latest.json10
-rw-r--r--website/robots.txt4
-rw-r--r--website/sitemap.xml8
13 files changed, 1108 insertions, 0 deletions
diff --git a/website/_headers b/website/_headers
new file mode 100644
index 00000000..e43c165c
--- /dev/null
+++ b/website/_headers
@@ -0,0 +1,19 @@
+/*
+ X-Frame-Options: SAMEORIGIN
+ X-Content-Type-Options: nosniff
+ Referrer-Policy: strict-origin-when-cross-origin
+
+/assets/*
+ Cache-Control: public, max-age=604800, immutable
+
+/install.sh
+ Content-Type: text/plain
+ Content-Disposition: inline
+
+/install
+ Content-Type: text/plain
+ Content-Disposition: inline
+
+/latest.json
+ Content-Type: application/json
+ Cache-Control: public, max-age=300
diff --git a/website/_redirects b/website/_redirects
new file mode 100644
index 00000000..2f13d2c1
--- /dev/null
+++ b/website/_redirects
@@ -0,0 +1 @@
+/install /install.sh 200
diff --git a/website/assets/demo.mp4 b/website/assets/demo.mp4
new file mode 100644
index 00000000..665fcb2f
--- /dev/null
+++ b/website/assets/demo.mp4
Binary files differ
diff --git a/website/assets/hero-screenshot.png b/website/assets/hero-screenshot.png
new file mode 100644
index 00000000..f1c09c1a
--- /dev/null
+++ b/website/assets/hero-screenshot.png
Binary files differ
diff --git a/website/assets/logo.png b/website/assets/logo.png
new file mode 100644
index 00000000..9c2e60c1
--- /dev/null
+++ b/website/assets/logo.png
Binary files differ
diff --git a/website/assets/og-card.png b/website/assets/og-card.png
new file mode 100644
index 00000000..85d4e602
--- /dev/null
+++ b/website/assets/og-card.png
Binary files differ
diff --git a/website/assets/sidebar-agents.png b/website/assets/sidebar-agents.png
new file mode 100644
index 00000000..1d5c5041
--- /dev/null
+++ b/website/assets/sidebar-agents.png
Binary files differ
diff --git a/website/assets/sidebar-workspaces.png b/website/assets/sidebar-workspaces.png
new file mode 100644
index 00000000..a8160f1e
--- /dev/null
+++ b/website/assets/sidebar-workspaces.png
Binary files differ
diff --git a/website/index.html b/website/index.html
new file mode 100644
index 00000000..e064f447
--- /dev/null
+++ b/website/index.html
@@ -0,0 +1,978 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>herdr — herd your agents</title>
+ <meta name="description" content="Terminal-native agent multiplexer. Workspaces, tiled panes, agent detection, and a socket API that lets your agents control herdr too.">
+ <meta name="theme-color" content="#0d1117">
+ <link rel="canonical" href="https://herdr.dev/">
+
+ <!-- Open Graph -->
+ <meta property="og:type" content="website">
+ <meta property="og:site_name" content="herdr">
+ <meta property="og:title" content="herdr — herd your agents">
+ <meta property="og:description" content="Terminal-native agent multiplexer. Workspaces, tiled panes, agent detection, and a socket API that lets your agents control herdr too.">
+ <meta property="og:url" content="https://herdr.dev/">
+ <meta property="og:image" content="https://herdr.dev/assets/og-card.png">
+ <meta property="og:image:width" content="1200">
+ <meta property="og:image:height" content="630">
+
+ <!-- Twitter / X -->
+ <meta name="twitter:card" content="summary_large_image">
+ <meta name="twitter:title" content="herdr — herd your agents">
+ <meta name="twitter:description" content="Terminal-native agent multiplexer. Workspaces, tiled panes, agent detection, and a socket API.">
+ <meta name="twitter:image" content="https://herdr.dev/assets/og-card.png">
+
+ <link rel="icon" type="image/png" href="/assets/logo.png">
+ <link rel="apple-touch-icon" href="/assets/logo.png">
+ <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@400;500;700&display=swap" rel="stylesheet">
+ <style>
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
+
+ :root {
+ --bg: #0d1117;
+ --bg-raised: #161b22;
+ --bg-surface: #1c2129;
+ --border: #21262d;
+ --border-bright: #30363d;
+ --text: #e6edf3;
+ --text-muted: #8b949e;
+ --text-dim: #484f58;
+ --green: #4ade80;
+ --green-dim: rgba(74, 222, 128, 0.12);
+ --red: #f87171;
+ --blue: #60a5fa;
+ --yellow: #fbbf24;
+ --max-w: 1080px;
+ }
+
+ html {
+ background: var(--bg);
+ color: var(--text);
+ font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', monospace;
+ -webkit-font-smoothing: antialiased;
+ scroll-behavior: smooth;
+ }
+
+ body { overflow-x: hidden; }
+
+ /* ── Hero ── */
+ .hero {
+ position: relative;
+ max-width: var(--max-w);
+ margin: 0 auto;
+ padding: 4rem 2rem 0;
+ text-align: center;
+ overflow: hidden;
+ }
+
+ .hero-pasture {
+ position: absolute;
+ inset: 0;
+ overflow: hidden;
+ pointer-events: none;
+ z-index: 0;
+ }
+
+ .hero > *:not(.hero-pasture) {
+ position: relative;
+ z-index: 1;
+ }
+
+ .hero .sheep-el {
+ position: absolute;
+ font-family: 'JetBrains Mono', monospace;
+ line-height: 1.15;
+ white-space: pre;
+ pointer-events: none;
+ user-select: none;
+ will-change: transform;
+ }
+
+ .hero-logo {
+ width: 80px;
+ height: 80px;
+ border-radius: 18px;
+ margin-bottom: 1.25rem;
+ }
+
+ .hero h1 {
+ font-size: 3rem;
+ font-weight: 700;
+ letter-spacing: -0.03em;
+ color: #fff;
+ }
+
+ .hero-tagline {
+ font-size: 1.1rem;
+ color: var(--green);
+ margin: 0.25rem 0 1.25rem;
+ }
+
+ .hero-desc {
+ font-size: 0.875rem;
+ color: var(--text-muted);
+ line-height: 1.8;
+ max-width: 640px;
+ margin: 0 auto 2rem;
+ }
+
+ .hero-desc p + p { margin-top: 0.6rem; }
+
+ /* install box */
+ .install-box {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.75rem;
+ background: var(--bg-raised);
+ border: 1px solid var(--border);
+ border-radius: 8px;
+ padding: 0.65rem 1rem;
+ font-size: 0.825rem;
+ margin-bottom: 0.75rem;
+ transition: border-color 0.2s;
+ }
+
+ .install-box:hover { border-color: var(--border-bright); }
+ .install-box .prompt { color: var(--green); }
+ .install-box code { color: var(--text); }
+
+ .copy-btn {
+ background: none;
+ border: 1px solid var(--border);
+ color: var(--text-dim);
+ font-family: inherit;
+ font-size: 0.7rem;
+ padding: 0.2rem 0.5rem;
+ border-radius: 4px;
+ cursor: pointer;
+ transition: all 0.2s;
+ }
+ .copy-btn:hover { border-color: var(--green); color: var(--green); }
+ .copy-btn.copied { border-color: var(--green); color: var(--green); }
+
+ .hero-links {
+ display: flex;
+ justify-content: center;
+ gap: 1.5rem;
+ margin-top: 0.5rem;
+ font-size: 0.8rem;
+ }
+ .hero-links a {
+ color: var(--text-dim);
+ text-decoration: none;
+ transition: color 0.2s;
+ }
+ .hero-links a:hover { color: var(--green); }
+
+ /* screenshot */
+ .hero-screenshot {
+ max-width: var(--max-w);
+ margin: 3rem auto 0;
+ padding: 0 2rem;
+ }
+
+ .screenshot-frame {
+ position: relative;
+ border-radius: 12px;
+ overflow: hidden;
+ border: 1px solid var(--border);
+ box-shadow:
+ 0 0 0 1px rgba(0,0,0,0.3),
+ 0 24px 80px rgba(0,0,0,0.5),
+ 0 0 120px rgba(74, 222, 128, 0.03);
+ }
+
+ .screenshot-frame img,
+ .screenshot-frame video {
+ display: block;
+ width: 100%;
+ height: auto;
+ }
+
+ .screenshot-label {
+ text-align: center;
+ font-size: 0.7rem;
+ color: var(--text-dim);
+ margin-top: 1rem;
+ }
+
+ /* ── Divider ── */
+ .section-gap { height: 5rem; }
+
+ /* ── Two-column features ── */
+ .features {
+ max-width: var(--max-w);
+ margin: 0 auto;
+ padding: 0 2rem;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 2rem;
+ }
+
+ .feature-card {
+ background: var(--bg-raised);
+ border: 1px solid var(--border);
+ border-radius: 10px;
+ padding: 2rem;
+ }
+
+ .feature-card h2 {
+ font-size: 1rem;
+ font-weight: 700;
+ margin-bottom: 0.25rem;
+ color: #fff;
+ }
+
+ .feature-card .subtitle {
+ font-size: 0.75rem;
+ color: var(--green);
+ margin-bottom: 1.25rem;
+ }
+
+ .feature-list {
+ list-style: none;
+ }
+
+ .feature-list li {
+ font-size: 0.8rem;
+ color: var(--text-muted);
+ line-height: 1.7;
+ padding-left: 1.2rem;
+ position: relative;
+ }
+
+ .feature-list li::before {
+ content: '›';
+ position: absolute;
+ left: 0;
+ color: var(--text-dim);
+ }
+
+ .feature-list li + li { margin-top: 0.4rem; }
+
+ /* ── Awareness section ── */
+ .awareness {
+ max-width: var(--max-w);
+ margin: 0 auto;
+ padding: 0 2rem;
+ }
+
+ .awareness-header {
+ margin-bottom: 1.5rem;
+ }
+
+ .awareness-header h2 {
+ font-size: 1rem;
+ font-weight: 700;
+ color: #fff;
+ margin-bottom: 0.3rem;
+ }
+
+ .awareness-desc {
+ font-size: 0.8rem;
+ color: var(--text-muted);
+ line-height: 1.7;
+ }
+
+ .awareness-dual {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 2rem;
+ margin-bottom: 1.5rem;
+ }
+
+ .awareness-panel {
+ background: var(--bg-raised);
+ border: 1px solid var(--border);
+ border-radius: 10px;
+ padding: 1.5rem;
+ display: flex;
+ gap: 1.25rem;
+ align-items: flex-start;
+ }
+
+ .awareness-panel-img {
+ flex-shrink: 0;
+ border: 1px solid var(--border);
+ border-radius: 6px;
+ overflow: hidden;
+ }
+
+ .awareness-panel-img img {
+ display: block;
+ height: auto;
+ width: auto;
+ max-height: 120px;
+ image-rendering: auto;
+ }
+
+ .awareness-panel-text h3 {
+ font-size: 0.85rem;
+ font-weight: 700;
+ color: #fff;
+ margin-bottom: 0.4rem;
+ }
+
+ .awareness-panel-text p {
+ font-size: 0.75rem;
+ color: var(--text-muted);
+ line-height: 1.7;
+ }
+
+ .state-bar {
+ display: flex;
+ justify-content: center;
+ gap: 2rem;
+ padding: 1rem 0 0;
+ }
+
+ .state-bar-item {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-size: 0.75rem;
+ color: var(--text-muted);
+ }
+
+ .state-dot {
+ flex-shrink: 0;
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ display: inline-block;
+ }
+
+ .state-dot.red { background: var(--red); box-shadow: 0 0 8px rgba(248,113,113,0.4); }
+ .state-dot.blue { background: var(--blue); box-shadow: 0 0 8px rgba(96,165,250,0.4); }
+ .state-dot.yellow { background: var(--yellow); box-shadow: 0 0 8px rgba(251,191,36,0.3); }
+ .state-dot.green { background: var(--green); opacity: 0.5; }
+
+ /* ── Agents table ── */
+ .agents-section {
+ max-width: var(--max-w);
+ margin: 0 auto;
+ padding: 0 2rem;
+ }
+
+ .agents-section h2 {
+ font-size: 1rem;
+ font-weight: 700;
+ color: #fff;
+ margin-bottom: 0.3rem;
+ }
+
+ .agents-section .section-desc {
+ font-size: 0.775rem;
+ color: var(--text-muted);
+ margin-bottom: 1.25rem;
+ line-height: 1.6;
+ }
+
+ .agents-table-wrap {
+ border: 1px solid var(--border);
+ border-radius: 10px;
+ overflow: hidden;
+ }
+
+ .agents-table {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 0.8rem;
+ }
+
+ .agents-table th {
+ text-align: left;
+ padding: 0.7rem 1rem;
+ color: var(--text-muted);
+ font-weight: 500;
+ font-size: 0.7rem;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ background: var(--bg-surface);
+ border-bottom: 1px solid var(--border);
+ }
+
+ .agents-table td {
+ padding: 0.6rem 1rem;
+ border-bottom: 1px solid var(--border);
+ color: var(--text-muted);
+ }
+
+ .agents-table tr:last-child td { border-bottom: none; }
+
+ .agents-table td:first-child {
+ color: var(--text);
+ font-weight: 500;
+ }
+
+ .agents-table a {
+ color: inherit;
+ text-decoration: none;
+ border-bottom: 1px solid var(--border);
+ transition: all 0.2s;
+ }
+ .agents-table a:hover { color: var(--green); border-color: var(--green); }
+
+ .check { color: var(--green); }
+ .partial { color: var(--yellow); }
+ .untested { color: var(--text-dim); font-size: 0.7rem; }
+
+ /* ── How it works ── */
+ .how-section {
+ max-width: var(--max-w);
+ margin: 0 auto;
+ padding: 0 2rem;
+ }
+
+ .how-section h2 {
+ font-size: 1rem;
+ font-weight: 700;
+ color: #fff;
+ margin-bottom: 1.25rem;
+ }
+
+ .how-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 1.5rem;
+ }
+
+ .how-step {
+ background: var(--bg-raised);
+ border: 1px solid var(--border);
+ border-radius: 10px;
+ padding: 1.5rem;
+ }
+
+ .how-step .step-num {
+ font-size: 0.7rem;
+ color: var(--green);
+ margin-bottom: 0.5rem;
+ }
+
+ .how-step h3 {
+ font-size: 0.85rem;
+ font-weight: 700;
+ color: #fff;
+ margin-bottom: 0.4rem;
+ }
+
+ .how-step p {
+ font-size: 0.75rem;
+ color: var(--text-muted);
+ line-height: 1.65;
+ }
+
+ .how-step code {
+ font-size: 0.725rem;
+ background: var(--bg);
+ padding: 0.15rem 0.35rem;
+ border-radius: 3px;
+ color: var(--text);
+ }
+
+ /* ── API teaser ── */
+ .api-section {
+ max-width: var(--max-w);
+ margin: 0 auto;
+ padding: 0 2rem;
+ }
+
+ .api-card {
+ background: var(--bg-raised);
+ border: 1px solid var(--border);
+ border-radius: 10px;
+ padding: 2rem;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 2rem;
+ align-items: start;
+ }
+
+ .api-card h2 {
+ font-size: 1rem;
+ font-weight: 700;
+ color: #fff;
+ margin-bottom: 0.3rem;
+ }
+
+ .api-card .subtitle {
+ font-size: 0.75rem;
+ color: var(--green);
+ margin-bottom: 1rem;
+ }
+
+ .api-card p {
+ font-size: 0.8rem;
+ color: var(--text-muted);
+ line-height: 1.7;
+ }
+
+ .api-card p + p { margin-top: 0.6rem; }
+
+ .api-doc-links {
+ display: flex;
+ gap: 0.75rem;
+ margin-top: 1.25rem;
+ }
+
+ .api-doc-links a {
+ font-size: 0.75rem;
+ color: var(--text);
+ text-decoration: none;
+ padding: 0.4rem 0.75rem;
+ border: 1px solid var(--border);
+ border-radius: 6px;
+ transition: all 0.2s;
+ }
+ .api-doc-links a:hover { border-color: var(--green); color: var(--green); }
+
+ .code-block {
+ background: var(--bg);
+ border: 1px solid var(--border);
+ border-radius: 8px;
+ padding: 1.25rem;
+ overflow-x: auto;
+ }
+
+ .code-block pre {
+ font-size: 0.725rem;
+ line-height: 1.8;
+ color: var(--text-muted);
+ }
+
+ .code-block .comment { color: var(--text-dim); }
+ .code-block .cmd { color: var(--green); }
+ .code-block .flag { color: var(--blue); }
+ .code-block .str { color: var(--yellow); }
+
+ /* ── Footer ── */
+ .footer {
+ max-width: var(--max-w);
+ margin: 0 auto;
+ padding: 4rem 2rem 3rem;
+ text-align: center;
+ }
+
+ .footer-line {
+ border: none;
+ border-top: 1px solid var(--border);
+ margin-bottom: 2rem;
+ }
+
+ .footer p {
+ font-size: 0.75rem;
+ color: var(--text-dim);
+ line-height: 1.8;
+ }
+
+ .footer a {
+ color: var(--text-muted);
+ text-decoration: none;
+ transition: color 0.2s;
+ }
+ .footer a:hover { color: var(--green); }
+
+ /* ── Responsive ── */
+ @media (max-width: 768px) {
+ .hero { padding-top: 3rem; }
+ .hero h1 { font-size: 2.25rem; }
+ .features { grid-template-columns: 1fr; }
+ .how-grid { grid-template-columns: 1fr; }
+ .api-card { grid-template-columns: 1fr; }
+ .awareness-dual { grid-template-columns: 1fr; }
+ .state-bar { gap: 1rem; flex-wrap: wrap; }
+ .hero-screenshot { padding: 0 1rem; }
+ .state-grid { grid-template-columns: 1fr 1fr; }
+ }
+
+ @media (max-width: 480px) {
+ .hero h1 { font-size: 1.75rem; }
+ .install-box { font-size: 0.7rem; padding: 0.5rem 0.75rem; }
+ .state-grid { grid-template-columns: 1fr; }
+ }
+ </style>
+</head>
+<body>
+
+ <!-- ── Hero ── -->
+ <section class="hero" id="hero">
+ <img src="/assets/logo.png" alt="herdr" class="hero-logo">
+ <h1>herdr</h1>
+ <p class="hero-tagline">herd your agents.</p>
+ <div class="hero-desc">
+ <p>a terminal-native agent multiplexer. workspaces, tiled panes, automatic agent detection, and a socket API. all inside your existing terminal. no electron, no web dashboard, no gui window.</p>
+ <p>a shared control surface for you and your agents.</p>
+ </div>
+ <div class="install-box">
+ <span class="prompt">$</span>
+ <code id="install-cmd">curl -fsSL https://herdr.dev/install.sh | sh</code>
+ <button class="copy-btn" id="copy-btn">copy</button>
+ </div>
+ <div class="hero-links">
+ <a href="https://github.com/ogulcancelik/herdr">github</a>
+ <a href="https://github.com/ogulcancelik/herdr/blob/master/CONFIGURATION.md">docs</a>
+ <a href="https://github.com/ogulcancelik/herdr/blob/master/SOCKET_API.md">api</a>
+ </div>
+ </section>
+
+ <!-- ── Demo ── -->
+ <div class="hero-screenshot">
+ <div class="screenshot-frame">
+ <video autoplay muted loop playsinline preload="auto" poster="/assets/hero-screenshot.png">
+ <source src="/assets/demo.mp4" type="video/mp4">
+ </video>
+ </div>
+ </div>
+
+ <div class="section-gap"></div>
+
+ <!-- ── For you / For your agents ── -->
+ <section class="features">
+ <div class="feature-card">
+ <h2>for you</h2>
+ <p class="subtitle">supervise, triage, act</p>
+ <ul class="feature-list">
+ <li>one place to see all running agents across workspaces</li>
+ <li>sidebar rolls up each workspace to its most urgent state</li>
+ <li>switch contexts instantly — click or keyboard</li>
+ <li>sound alerts and toast notifications for background events</li>
+ <li>mouse-native: click panes, drag borders, select text to copy</li>
+ <li>session persistence — close and reopen, everything restores</li>
+ <li>9 built-in themes, full color token overrides</li>
+ </ul>
+ </div>
+ <div class="feature-card">
+ <h2>for your agents</h2>
+ <p class="subtitle">orchestrate, spawn, wait</p>
+ <ul class="feature-list">
+ <li>create workspaces and split panes programmatically</li>
+ <li>spawn other agents in sibling panes</li>
+ <li>read output from any pane in the session</li>
+ <li>send text and keys into other panes</li>
+ <li>wait for output patterns or agent state changes</li>
+ <li>subscribe to real-time events over the socket</li>
+ <li>ship an agent skill or use the socket API directly</li>
+ </ul>
+ </div>
+ </section>
+
+ <div class="section-gap"></div>
+
+ <!-- ── Awareness ── -->
+ <section class="awareness">
+ <div class="awareness-header">
+ <h2>ambient awareness</h2>
+ <p class="awareness-desc">the sidebar is split into two layers. scan the workspace list for the most urgent signal, then drill into the agents causing it.</p>
+ </div>
+ <div class="awareness-dual">
+ <div class="awareness-panel">
+ <div class="awareness-panel-img">
+ <img src="/assets/sidebar-workspaces.png" alt="herdr sidebar workspace list">
+ </div>
+ <div class="awareness-panel-text">
+ <h3>workspaces</h3>
+ <p>each workspace shows one aggregate dot — the most urgent state across all its agents. yellow means something is working. you scan the full list in a glance.</p>
+ </div>
+ </div>
+ <div class="awareness-panel">
+ <div class="awareness-panel-img">
+ <img src="/assets/sidebar-agents.png" alt="herdr sidebar agent list">
+ </div>
+ <div class="awareness-panel-text">
+ <h3>agents</h3>
+ <p>the bottom section shows which specific agents are running in the selected workspace, with their individual state. pi is working, droid is idle.</p>
+ </div>
+ </div>
+ </div>
+ <div class="state-bar">
+ <div class="state-bar-item"><span class="state-dot red"></span> blocked</div>
+ <div class="state-bar-item"><span class="state-dot blue"></span> done</div>
+ <div class="state-bar-item"><span class="state-dot yellow"></span> working</div>
+ <div class="state-bar-item"><span class="state-dot green"></span> idle</div>
+ </div>
+ </section>
+
+ <div class="section-gap"></div>
+
+ <!-- ── How it works ── -->
+ <section class="how-section">
+ <h2>how it works</h2>
+ <div class="how-grid">
+ <div class="how-step">
+ <div class="step-num">01</div>
+ <h3>install and launch</h3>
+ <p>one binary, no dependencies. run <code>herdr</code> in your terminal. onboarding takes 10 seconds.</p>
+ </div>
+ <div class="how-step">
+ <div class="step-num">02</div>
+ <h3>create workspaces</h3>
+ <p>press <code>n</code> to create a workspace. it opens as a terminal context, labels itself from git repo or folder name.</p>
+ </div>
+ <div class="how-step">
+ <div class="step-num">03</div>
+ <h3>launch agents</h3>
+ <p>start your agents in panes like you normally would. herdr detects them automatically — no hooks, no config.</p>
+ </div>
+ </div>
+ </section>
+
+ <div class="section-gap"></div>
+
+ <!-- ── Supported agents ── -->
+ <section class="agents-section">
+ <h2>supported agents</h2>
+ <p class="section-desc">herdr detects agents by reading foreground process and terminal output patterns. zero config required.</p>
+ <div class="agents-table-wrap">
+ <table class="agents-table">
+ <thead>
+ <tr>
+ <th>agent</th>
+ <th>idle / done</th>
+ <th>working</th>
+ <th>blocked</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><a href="https://pi.dev">pi</a></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="partial">partial</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://docs.anthropic.com/en/docs/claude-code">claude code</a></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://github.com/openai/codex">codex</a></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://factory.ai">droid</a></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://ampcode.com">amp</a></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="partial">partial</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://github.com/anomalyco/opencode">opencode</a></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ <td><span class="check">✓</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://github.com/google-gemini/gemini-cli">gemini cli</a></td>
+ <td colspan="3"><span class="untested">detected, not fully tested</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://cursor.com/cli">cursor agent</a></td>
+ <td colspan="3"><span class="untested">detected, not fully tested</span></td>
+ </tr>
+ <tr>
+ <td><a href="https://github.com/cline/cline">cline</a></td>
+ <td colspan="3"><span class="untested">detected, not fully tested</span></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </section>
+
+ <div class="section-gap"></div>
+
+ <!-- ── API ── -->
+ <section class="api-section">
+ <div class="api-card">
+ <div>
+ <h2>socket api</h2>
+ <p class="subtitle">agents can use herdr too</p>
+ <p>herdr exposes a local unix socket that agents can talk to directly. create workspaces, split panes, spawn agents, read output, wait for state changes.</p>
+ <p>the same surface is available as CLI commands (<code>herdr workspace</code>, <code>herdr pane</code>, <code>herdr wait</code>) and as a reusable agent skill.</p>
+ <div class="api-doc-links">
+ <a href="https://github.com/ogulcancelik/herdr/blob/master/SOCKET_API.md">socket api docs →</a>
+ <a href="https://github.com/ogulcancelik/herdr/blob/master/SKILL.md">agent skill →</a>
+ </div>
+ </div>
+ <div class="code-block">
+ <pre><span class="comment"># create a workspace</span>
+<span class="cmd">herdr</span> workspace create <span class="flag">--root</span> <span class="str">~/project</span>
+
+<span class="comment"># split a pane and run a command</span>
+<span class="cmd">herdr</span> pane split <span class="flag">--workspace</span> <span class="str">1</span>
+<span class="cmd">herdr</span> pane send <span class="flag">--pane</span> <span class="str">1-2</span> <span class="flag">--text</span> <span class="str">"npm test"</span>
+
+<span class="comment"># wait for an agent to finish</span>
+<span class="cmd">herdr</span> wait <span class="flag">--pane</span> <span class="str">1-1</span> <span class="flag">--state</span> <span class="str">idle</span>
+
+<span class="comment"># read pane output</span>
+<span class="cmd">herdr</span> pane read <span class="flag">--pane</span> <span class="str">1-2</span> <span class="flag">--lines</span> <span class="str">50</span></pre>
+ </div>
+ </div>
+ </section>
+
+ <div class="section-gap"></div>
+
+ <!-- ── Footer ── -->
+ <footer class="footer">
+ <hr class="footer-line">
+ <p>
+ <a href="https://github.com/ogulcancelik/herdr">github</a> ·
+ <a href="https://github.com/ogulcancelik/herdr/blob/master/CONFIGURATION.md">configuration</a> ·
+ <a href="https://github.com/ogulcancelik/herdr/blob/master/SOCKET_API.md">api</a> ·
+ <a href="https://github.com/ogulcancelik/herdr/releases">releases</a>
+ </p>
+ <p style="margin-top: 0.75rem;">linux · macos · agpl-3.0</p>
+ </footer>
+
+ <script>
+ (function() {
+ 'use strict';
+
+ // ── Sheep ──
+ var hero = document.getElementById('hero');
+ var pasture = document.createElement('div');
+ pasture.className = 'hero-pasture';
+ pasture.setAttribute('aria-hidden', 'true');
+ hero.prepend(pasture);
+
+ var SR = [
+ [' ,ww',' wWWWWWWW_)'," `WWWWWW'",' II II'],
+ [' ,ww',' wWWWWWWW_)'," `WWWWWW'",' II II']
+ ];
+ var SL = [
+ [' ww,','(_WWWWWWWw'," 'WWWWWW`",' II II'],
+ [' ww,','(_WWWWWWWw'," 'WWWWWW`",' II II']
+ ];
+
+ var heroW = hero.offsetWidth;
+ var heroH = hero.offsetHeight;
+ var heroRect = hero.getBoundingClientRect();
+ var mx = -9999, my = -9999;
+
+ document.addEventListener('mousemove', function(e) {
+ mx = e.clientX - heroRect.left;
+ my = e.clientY - heroRect.top;
+ });
+ document.addEventListener('mouseleave', function() { mx = -9999; my = -9999; });
+
+ window.addEventListener('resize', function() {
+ heroW = hero.offsetWidth;
+ heroH = hero.offsetHeight;
+ heroRect = hero.getBoundingClientRect();
+ });
+ window.addEventListener('scroll', function() {
+ heroRect = hero.getBoundingClientRect();
+ });
+
+ var flock = [];
+ var count = window.matchMedia('(max-width: 640px)').matches ? 4 : 8;
+
+ for (var i = 0; i < count; i++) {
+ var el = document.createElement('pre');
+ el.className = 'sheep-el';
+ var opacity = 0.04 + Math.random() * 0.035;
+ var size = 10 + Math.random() * 4;
+ el.style.cssText = 'font-size:' + size + 'px;color:rgba(255,255,255,' + opacity + ')';
+ pasture.appendChild(el);
+
+ flock.push({
+ el: el,
+ x: Math.random() * heroW,
+ y: 30 + Math.random() * (heroH - 80),
+ dir: Math.random() > 0.5 ? 1 : -1,
+ speed: 0.15 + Math.random() * 0.3,
+ frame: 0,
+ ft: 0,
+ fi: 400 + Math.random() * 300,
+ svx: 0,
+ svy: 0
+ });
+ }
+
+ var last = 0;
+ function tick(ts) {
+ var dt = Math.min(ts - last, 100);
+ last = ts;
+ for (var i = 0; i < flock.length; i++) {
+ var s = flock[i];
+ s.ft += dt;
+ if (s.ft > s.fi) { s.ft = 0; s.frame ^= 1; }
+
+ // mouse scatter
+ var dx = s.x - mx, dy = s.y - my;
+ var d = Math.sqrt(dx * dx + dy * dy);
+ if (d < 120 && d > 1) {
+ var f = (1 - d / 120) * 0.6;
+ s.svx += (dx / d) * f;
+ s.svy += (dy / d) * f;
+ }
+ s.x += s.svx;
+ s.y += s.svy;
+ s.svx *= 0.97;
+ s.svy *= 0.97;
+
+ s.x += s.dir * s.speed * (dt / 16);
+ if (s.dir > 0 && s.x > heroW + 100) s.x = -100;
+ if (s.dir < 0 && s.x < -100) s.x = heroW + 100;
+ if (s.y < -40) s.y = heroH + 20;
+ if (s.y > heroH + 40) s.y = -20;
+ var frames = s.dir > 0 ? SR : SL;
+ s.el.textContent = frames[s.frame].join('\n');
+ s.el.style.transform = 'translate3d(' + s.x + 'px,' + s.y + 'px,0)';
+ }
+ requestAnimationFrame(tick);
+ }
+ requestAnimationFrame(function(ts) { last = ts; tick(ts); });
+
+ // ── Copy ──
+ var copyBtn = document.getElementById('copy-btn');
+ var installCmd = document.getElementById('install-cmd');
+
+ function fallbackCopy(text) {
+ var ta = document.createElement('textarea');
+ ta.value = text;
+ ta.style.cssText = 'position:fixed;left:-9999px';
+ document.body.appendChild(ta);
+ ta.select();
+ document.execCommand('copy');
+ document.body.removeChild(ta);
+ }
+
+ function showCopied() {
+ copyBtn.textContent = 'copied!';
+ copyBtn.classList.add('copied');
+ setTimeout(function() {
+ copyBtn.textContent = 'copy';
+ copyBtn.classList.remove('copied');
+ }, 2000);
+ }
+
+ copyBtn.addEventListener('click', function() {
+ var text = installCmd.textContent;
+ if (navigator.clipboard && navigator.clipboard.writeText) {
+ navigator.clipboard.writeText(text).then(showCopied).catch(function() {
+ fallbackCopy(text);
+ showCopied();
+ });
+ } else {
+ fallbackCopy(text);
+ showCopied();
+ }
+ });
+ })();
+ </script>
+</body>
+</html>
diff --git a/website/install.sh b/website/install.sh
new file mode 100755
index 00000000..e705be08
--- /dev/null
+++ b/website/install.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+set -eu
+
+REPO="ogulcancelik/herdr"
+BIN="herdr"
+INSTALL_DIR="${HERDR_INSTALL_DIR:-$HOME/.local/bin}"
+
+main() {
+ echo ""
+ echo " ,ww"
+ echo " wWWWWWWW_) herdr installer"
+ echo " \`WWWWWW' herdr.dev"
+ echo " II II"
+ echo ""
+
+ # detect platform
+ OS="$(uname -s)"
+ case "$OS" in
+ Linux) os="linux" ;;
+ Darwin) os="macos" ;;
+ *) err "unsupported OS: $OS" ;;
+ esac
+
+ ARCH="$(uname -m)"
+ case "$ARCH" in
+ x86_64|amd64) arch="x86_64" ;;
+ aarch64|arm64) arch="aarch64" ;;
+ *) err "unsupported architecture: $ARCH" ;;
+ esac
+
+ log "detected ${os}/${arch}"
+
+ # check dependencies
+ need curl
+
+ # download the latest binary directly via GitHub's stable redirect.
+ # this avoids the releases API, which can return transient 403s.
+ ASSET="${BIN}-${os}-${arch}"
+ URL="https://github.com/${REPO}/releases/latest/download/${ASSET}"
+
+ log "downloading latest release..."
+ TMP="$(mktemp -d)"
+ trap 'rm -rf "$TMP"' EXIT
+
+ if ! curl -fsSL --retry 3 --connect-timeout 10 --max-time 120 "$URL" -o "${TMP}/${BIN}"; then
+ err "download failed. check https://github.com/${REPO}/releases"
+ fi
+
+ # install
+ mkdir -p "$INSTALL_DIR"
+ mv "${TMP}/${BIN}" "${INSTALL_DIR}/${BIN}"
+ chmod +x "${INSTALL_DIR}/${BIN}"
+
+ log "installed ${BIN} to ${INSTALL_DIR}/${BIN}"
+
+ # check PATH
+ case ":${PATH}:" in
+ *":${INSTALL_DIR}:"*) ;;
+ *)
+ echo ""
+ warn "${INSTALL_DIR} is not in your PATH"
+ echo " add it to your shell config:"
+ echo ""
+ echo " export PATH=\"${INSTALL_DIR}:\$PATH\""
+ echo ""
+ ;;
+ esac
+
+ # verify
+ if command -v "$BIN" >/dev/null 2>&1; then
+ echo ""
+ log "ready. run 'herdr' to get started."
+ fi
+
+ echo ""
+}
+
+log() { echo " \033[32m>\033[0m $1"; }
+warn() { echo " \033[33m!\033[0m $1"; }
+err() { echo " \033[31m✗\033[0m $1" >&2; exit 1; }
+
+need() {
+ if ! command -v "$1" >/dev/null 2>&1; then
+ err "requires '$1' — please install it first"
+ fi
+}
+
+main "$@"
diff --git a/website/latest.json b/website/latest.json
new file mode 100644
index 00000000..8113b662
--- /dev/null
+++ b/website/latest.json
@@ -0,0 +1,10 @@
+{
+ "version": "0.4.2",
+ "notes_url": "https://github.com/ogulcancelik/herdr/releases/tag/v0.4.2",
+ "assets": {
+ "linux-x86_64": "https://github.com/ogulcancelik/herdr/releases/download/v0.4.2/herdr-linux-x86_64",
+ "linux-aarch64": "https://github.com/ogulcancelik/herdr/releases/download/v0.4.2/herdr-linux-aarch64",
+ "macos-x86_64": "https://github.com/ogulcancelik/herdr/releases/download/v0.4.2/herdr-macos-x86_64",
+ "macos-aarch64": "https://github.com/ogulcancelik/herdr/releases/download/v0.4.2/herdr-macos-aarch64"
+ }
+}
diff --git a/website/robots.txt b/website/robots.txt
new file mode 100644
index 00000000..37e7285b
--- /dev/null
+++ b/website/robots.txt
@@ -0,0 +1,4 @@
+User-agent: *
+Allow: /
+
+Sitemap: https://herdr.dev/sitemap.xml
diff --git a/website/sitemap.xml b/website/sitemap.xml
new file mode 100644
index 00000000..99a706d5
--- /dev/null
+++ b/website/sitemap.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+ <url>
+ <loc>https://herdr.dev/</loc>
+ <lastmod>2026-03-27</lastmod>
+ <priority>1.0</priority>
+ </url>
+</urlset>