herdr/website/index.html

1046 lines
58 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Herdr — one terminal for the whole herd</title>
<meta
name="description"
content="Terminal-native agent runtime and multiplexer. Run AI coding agents in real panes, detach and reattach, SSH in, see state, and orchestrate through the CLI/socket API."
/>
<meta name="theme-color" content="#f0eee9" />
<link rel="canonical" href="https://herdr.dev/" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="Herdr" />
<meta property="og:title" content="Herdr — one terminal for the whole herd" />
<meta
property="og:description"
content="Terminal-native agent runtime and multiplexer. Detach, reattach, SSH in, and keep every agent visible."
/>
<meta property="og:url" content="https://herdr.dev/" />
<meta
property="og:image"
content="https://herdr.dev/assets/og-card-v6.png"
/>
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Herdr — One terminal. The whole herd." />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Herdr — one terminal for the whole herd" />
<meta
name="twitter:description"
content="Terminal-native agent runtime and multiplexer. Detach, reattach, SSH in, and keep every agent visible."
/>
<meta
name="twitter:image"
content="https://herdr.dev/assets/og-card-v6.png"
/>
<meta name="twitter:image:alt" content="Herdr — One terminal. The whole herd." />
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon.png?v=14" />
<link rel="apple-touch-icon" href="/assets/logo.png" />
<link
rel="preload"
href="/assets/jbm.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<script>
(function () {
var saved = localStorage.getItem("herdr-palette");
var system = window.matchMedia("(prefers-color-scheme: dark)").matches
? "tokyo-night"
: "tokyo-night-day";
document.documentElement.setAttribute("data-palette", saved || system);
})();
</script>
<link rel="stylesheet" href="/css/style.css?v=20" />
</head>
<body>
<header class="site-header">
<nav class="nav" aria-label="Primary navigation">
<a class="brand" href="/" aria-label="Herdr home">
<span class="brand-logo" aria-hidden="true"></span>
<span>herdr</span>
</a>
<div class="nav-links">
<a href="/compare/">Compare</a>
<a href="/docs/">Docs</a>
<a href="/docs/quick-start/">Quick start</a>
<a href="/docs/socket-api/">API</a>
<a href="https://github.com/ogulcancelik/herdr">GitHub</a>
</div>
<div class="nav-tools">
<a class="nav-cta" href="/docs/install/">Install</a>
</div>
</nav>
</header>
<main>
<section class="hero" id="hero">
<div class="hero-left">
<div class="hero-copy">
<p class="eyebrow">
<span class="status-dot dot-done"></span>
Terminal-native agent runtime
</p>
<h1>One terminal. The whole herd.</h1>
<p class="hero-lede">
Herdr is an agent runtime that runs inside your terminal.
Keep your shell, SSH setup, fonts, and keybinds; add
tmux-style persistence, mouse-native panes,
<span class="state blocked">blocked</span>,
<span class="state working">working</span>, and
<span class="state done">done</span> agent state, and an
API agents can drive.
</p>
<div class="hero-actions">
<a class="button button-primary" href="/docs/quick-start/"
>Quick start</a
>
<a class="button button-secondary" href="/docs/"
>Read the docs</a
>
</div>
<div class="install-panel" aria-label="Install options">
<div class="install-methods" role="group" aria-label="Install method">
<button
class="install-method is-active"
type="button"
data-command="curl -fsSL https://herdr.dev/install.sh | sh"
data-size="compact"
aria-pressed="true"
>Direct</button>
<span aria-hidden="true">·</span>
<button
class="install-method"
type="button"
data-command="brew install herdr"
data-size="normal"
aria-pressed="false"
>Homebrew</button>
<span aria-hidden="true">·</span>
<button
class="install-method"
type="button"
data-command="nix run github:ogulcancelik/herdr"
data-size="normal"
aria-pressed="false"
>Nix flake</button>
</div>
<div class="install-card" aria-label="Install command">
<span class="prompt">$</span>
<code id="install-cmd" class="is-compact"
>curl -fsSL https://herdr.dev/install.sh | sh</code
>
<button id="copy-btn" type="button">Copy</button>
</div>
</div>
<p class="hero-note">
Install script · Homebrew core · Nix flake · single Rust
binary · no Electron
</p>
</div>
</div>
<div class="hero-right">
<figure class="hero-product-shot">
<div
class="herdr-ui-mock"
role="img"
aria-label="Stylized Herdr session with spaces, tabs, agent states, terminal panes, and a local docs server"
>
<aside class="mock-sidebar">
<div class="mock-sidebar-title">spaces</div>
<div class="mock-space active">
<span class="mock-dot dot-idle"></span>
<div><strong>herdr</strong><small>master</small></div>
</div>
<div class="mock-space">
<span class="mock-dot dot-blocked"></span>
<div><strong>llm-proxy</strong><small>master</small></div>
</div>
<div class="mock-space">
<span class="mock-dot dot-done"></span>
<div><strong>qmp</strong><small>autoresearch/qmp-ra…</small></div>
</div>
<div class="mock-sidebar-spacer"></div>
<div class="mock-sidebar-row"><span>new</span><span>menu</span></div>
<div class="mock-agent-title"><span>agents</span><span>all</span></div>
<div class="mock-agent"><span></span><div><strong>doc</strong><small>idle · pi</small></div></div>
<div class="mock-agent working"><span class="braille-spinner"></span><div><strong>custom-row</strong><small>working · pi</small></div></div>
<div class="mock-agent blocked"><span></span><div><strong>llm-proxy</strong><small>blocked · claude</small></div></div>
<div class="mock-agent done"><span></span><div><strong>qmp</strong><small>done · codex</small></div></div>
</aside>
<section class="mock-main">
<div class="mock-tabs">
<span>doc</span><span>custom-row</span><span class="active">herdr</span><span>+</span>
</div>
<div class="mock-panes">
<div class="mock-pane focused">
<div class="mock-prompt"><span>~/Projects/herdr</span> <em>master</em></div>
<div><b></b> <span class="cmd">printf</span> <span class="str">"one terminal. the whole herd.\n"</span> | <span class="cmd">cowsay</span></div>
<pre>-------------------------------
&lt; one terminal. the whole herd. &gt;
-------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||</pre>
<div class="mock-prompt"><span>~/Projects/herdr</span> <em>master</em></div>
<div><b></b> <span class="cursor"></span></div>
</div>
<div class="mock-pane">
<div class="mock-prompt"><span>~/Projects/herdr-worktrees/docs-site/website</span> <em>docs-site*</em></div>
<div><b></b> <span class="cmd">bun</span> run dev</div>
<div class="dim">$ node scripts/prepare-docs.mjs && astro dev</div>
<div><span class="time">02:10:44</span> <span class="blue">[types]</span> Generated 0ms</div>
<div><span class="time">02:10:44</span> <span class="blue">[content]</span> Synced content</div>
<br />
<div><span class="badge">astro</span> <span class="green">v5.18.1</span> ready in 668 ms</div>
<br />
<div class="url-line">┃ Local&nbsp;&nbsp; <span>http://localhost:4321/</span></div>
<div class="dim"> Network&nbsp; use --host to expose</div>
<br />
<div><span class="time">02:10:44</span> <span class="green">watching for file changes...</span></div>
</div>
</div>
</section>
</div>
<figcaption>
The whole herd in one terminal.
</figcaption>
</figure>
</div>
</section>
<section class="logo-cloud" aria-labelledby="logo-cloud-title">
<div class="logo-cloud-heading">
<p class="section-kicker">Used in the wild</p>
<h2 id="logo-cloud-title">Popular with engineers from</h2>
</div>
<div class="logo-marquee" aria-label="Company logos">
<div class="logo-track">
<div class="logo-row">
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/jetbrains.svg" alt="JetBrains" /><span>JetBrains</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/docker.svg" alt="Docker" /><span>Docker</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/vercel.svg" alt="Vercel" /><span>Vercel</span></div>
<div class="logo-card"><img width="94" height="32" src="/assets/company-logos/kimi-with-icon-light.svg" alt="Kimi" /><span>Kimi</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/sentry.svg" alt="Sentry" /><span>Sentry</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/google.svg" alt="Google" /><span>Google</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/nvidia.svg" alt="NVIDIA" /><span>NVIDIA</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/aws.svg" alt="AWS" /><span>AWS</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/bytedance.svg" alt="ByteDance" /><span>ByteDance</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/tencent.svg" alt="Tencent" /><span>Tencent</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/alibaba.svg" alt="Alibaba" /><span>Alibaba</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/salesforce.svg" alt="Salesforce" /><span>Salesforce</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/ibm.svg" alt="IBM" /><span>IBM</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/atlassian.svg" alt="Atlassian" /><span>Atlassian</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/whop.svg?v=2" alt="Whop" /><span>Whop</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/automattic.svg" alt="Automattic" /><span>Automattic</span></div>
</div>
<div class="logo-row" aria-hidden="true">
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/jetbrains.svg" alt="" /><span>JetBrains</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/docker.svg" alt="" /><span>Docker</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/vercel.svg" alt="" /><span>Vercel</span></div>
<div class="logo-card"><img width="94" height="32" src="/assets/company-logos/kimi-with-icon-light.svg" alt="" /><span>Kimi</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/sentry.svg" alt="" /><span>Sentry</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/google.svg" alt="" /><span>Google</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/nvidia.svg" alt="" /><span>NVIDIA</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/aws.svg" alt="" /><span>AWS</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/bytedance.svg" alt="" /><span>ByteDance</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/tencent.svg" alt="" /><span>Tencent</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/alibaba.svg" alt="" /><span>Alibaba</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/salesforce.svg" alt="" /><span>Salesforce</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/ibm.svg" alt="" /><span>IBM</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/atlassian.svg" alt="" /><span>Atlassian</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/whop.svg?v=2" alt="" /><span>Whop</span></div>
<div class="logo-card"><img width="82" height="22" src="/assets/company-logos/automattic.svg" alt="" /><span>Automattic</span></div>
</div>
</div>
</div>
</section>
<section class="section intro-section">
<p class="section-kicker">The missing layer</p>
<div class="section-heading-wide">
<h2>
Keep your terminal. Add the control surface.
</h2>
<p>
Desktop agent terminals give you app UI. tmux gives you
persistence. Herdr sits between them: a lightweight TUI
process with real terminal panes, clickable layout,
agent state, detach/reattach, remote attach, and a
runtime API.
</p>
</div>
<div class="contrast-grid" aria-label="What Herdr is not">
<article>
<span>not a terminal emulator</span>
<p>Use Ghostty, Kitty, iTerm, Alacritty, or any terminal you already trust.</p>
</article>
<article>
<span>not a browser dashboard</span>
<p>No web view, hosted control plane, account, or reconstructed chat surface.</p>
</article>
<article>
<span>more than tmux for agents</span>
<p>Persistence plus mouse-native panes, state rollups, and commands agents can call.</p>
</article>
</div>
</section>
<section class="section compare-section">
<div class="section-heading-wide">
<div>
<p class="section-kicker">Positioning</p>
<h2>tmux persistence, agent awareness, no terminal replacement.</h2>
</div>
<p>
tmux and Zellij own persistent terminal sessions. Desktop agent apps own dashboards, editors, or worktree flows. Herdr keeps the multiplexer inside your terminal and makes it agent-aware.
<a href="/compare/">See the full comparison →</a>
</p>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Capability</th>
<th>tmux / Zellij</th>
<th>agent apps</th>
<th>worktree orchestrators</th>
<th>Herdr</th>
</tr>
</thead>
<tbody>
<tr>
<td>Runs inside your terminal</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Persistent PTY sessions</td>
<td></td>
<td>limited</td>
<td>embedded</td>
<td></td>
</tr>
<tr>
<td>Remote SSH attach</td>
<td></td>
<td>limited</td>
<td>remote projects</td>
<td></td>
</tr>
<tr>
<td>Semantic agent state</td>
<td></td>
<td>partial</td>
<td>workspace status</td>
<td></td>
</tr>
<tr>
<td>Direct agent attach</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Agents can orchestrate it</td>
<td>scriptable</td>
<td>partial</td>
<td>workflow-owned</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="compare-cards" aria-label="Mobile comparison">
<article>
<h3>Runs inside your terminal</h3>
<span>tmux/Zellij <b></b></span>
<span>agent apps <b></b></span>
<span>worktree apps <b></b></span>
<span class="herdr">Herdr <b></b></span>
</article>
<article>
<h3>Persistent PTY sessions</h3>
<span>tmux/Zellij <b></b></span>
<span>agent apps <b>limited</b></span>
<span>worktree apps <b>embedded</b></span>
<span class="herdr">Herdr <b></b></span>
</article>
<article>
<h3>Remote SSH attach</h3>
<span>tmux/Zellij <b></b></span>
<span>agent apps <b>limited</b></span>
<span>worktree apps <b>remote projects</b></span>
<span class="herdr">Herdr <b></b></span>
</article>
<article>
<h3>Semantic agent state</h3>
<span>tmux/Zellij <b></b></span>
<span>agent apps <b>partial</b></span>
<span>worktree apps <b>workspace status</b></span>
<span class="herdr">Herdr <b></b></span>
</article>
<article>
<h3>Direct agent attach</h3>
<span>tmux/Zellij <b></b></span>
<span>agent apps <b></b></span>
<span>worktree apps <b></b></span>
<span class="herdr">Herdr <b></b></span>
</article>
<article>
<h3>Agents can orchestrate it</h3>
<span>tmux/Zellij <b>scriptable</b></span>
<span>agent apps <b>partial</b></span>
<span>worktree apps <b>workflow-owned</b></span>
<span class="herdr">Herdr <b></b></span>
</article>
</div>
</section>
<section class="section feature-split">
<div class="feature-copy">
<p class="section-kicker">Your terminal</p>
<h2>Same shell, same keybinds, real panes.</h2>
<p>
Herdr does not replace your terminal or wrap agents in a
reconstructed chat view. It runs real processes in PTYs,
then adds layout, click targets, state, persistence, and
automation around them.
</p>
<ul class="check-list">
<li>Use the mouse for panes, tabs, workspaces, and menus.</li>
<li>Keep your terminal fonts, shortcuts, SSH, and shell setup.</li>
<li>Stay keyboard-first, or disable mouse input entirely.</li>
</ul>
</div>
<figure class="feature-mock" role="img" aria-label="Herdr showing split terminal panes">
<div class="mock-panes feature-mock-panes">
<div class="mock-pane focused">
<div class="mock-prompt"><span>~/Projects/herdr</span> <em>master</em></div>
<div><b></b> <span class="cmd">just</span> <span class="str">test</span></div>
<div class="dim">cargo nextest run</div>
<div><span class="time">02:14:22</span> <span class="green">PASS</span> app::state::tests</div>
<div><span class="time">02:14:23</span> <span class="green">PASS</span> platform::pty::tests</div>
<div><span class="time">02:14:24</span> <span class="green">PASS</span> protocol::wire::tests</div>
<br />
<div><span class="green">3 passed</span> · 0 failed · 0.8s</div>
<div class="mock-prompt"><span>~/Projects/herdr</span> <em>master</em></div>
<div><b></b> <span class="cursor"></span></div>
</div>
<div class="mock-pane">
<div class="mock-prompt"><span>~/Projects/herdr</span> <em>master</em></div>
<div><b></b> <span class="cmd">git</span> <span class="str">status</span></div>
<div class="dim">On branch master</div>
<div>Your branch is up to date.</div>
<br />
<div class="dim">Changes not staged:</div>
<div><span class="red">M</span> src/app/state.rs</div>
<div><span class="green">??</span> docs/next/</div>
<br />
<div class="dim">2 files changed, 14 insertions</div>
</div>
</div>
</figure>
</section>
<section class="section pillars" aria-labelledby="pillars-title">
<div class="section-heading">
<p class="section-kicker">Core pillars</p>
<h2 id="pillars-title">Why terminal users switch.</h2>
</div>
<div class="pillar-grid">
<article class="pillar-card">
<span class="card-index">01</span>
<h3>Survives disconnects</h3>
<p>
Panes keep running in a background session server.
Close the terminal, lose SSH, or detach on purpose;
come back to the same herd later.
</p>
</article>
<article class="pillar-card">
<span class="card-index">02</span>
<h3>Runs where code lives</h3>
<p>
Use Herdr locally, inside any SSH session, or as a
thin client to a remote host. Keep credentials and
repos on the machine doing the work.
</p>
</article>
<article class="pillar-card">
<span class="card-index">03</span>
<h3>Mouse-native TUI</h3>
<p>
Click panes, tabs, workspaces, and agents. Drag
borders, select text, use right-click menus, then
stay on the keyboard whenever that is faster.
</p>
</article>
<article class="pillar-card">
<span class="card-index">04</span>
<h3>Agents can drive it</h3>
<p>
The CLI and socket API let agents create panes, run
commands, read output, wait for changes, and operate
their workspace without hand-shuffled terminals.
</p>
</article>
</div>
</section>
<section class="section access-section">
<div class="section-heading">
<p class="section-kicker">Local or remote</p>
<h2>Run Herdr where the work lives.</h2>
</div>
<div class="access-grid">
<article class="access-card">
<span class="access-label">local</span>
<h3>Your machine</h3>
<p>
Start a local session, split panes, create tabs, and
keep agents running while your terminal comes and
goes.
</p>
<pre><code>$ herdr</code></pre>
</article>
<article class="access-card">
<span class="access-label">ssh</span>
<h3>Any SSH client</h3>
<p>
Use Herdr like tmux on a remote box. The session
stays on the server after you detach.
</p>
<pre><code>$ ssh you@server
$ herdr</code></pre>
</article>
<article class="access-card">
<span class="access-label">thin client</span>
<h3>Remote attach</h3>
<p>
Point your local Herdr client at an SSH config host
and stream the remote TUI back to your terminal.
</p>
<pre><code>$ herdr --remote workbox</code></pre>
</article>
</div>
<div class="mobile-proof">
<div class="mobile-copy">
<p class="section-kicker">Responsive TUI</p>
<h3>Mobile-first when the terminal gets small.</h3>
<p>
Herdr stays usable over SSH from a phone or tablet.
The terminal view remains real, while narrow screens
get a switcher built for touch-sized decisions.
</p>
</div>
<div class="mobile-shots">
<figure>
<img
src="/assets/mobile-agent-session-v2.jpeg"
alt="Herdr agent session over SSH on a phone"
loading="lazy"
/>
<figcaption>agent session over SSH</figcaption>
</figure>
<figure>
<img
src="/assets/mobile-switch-menu-v2.jpeg"
alt="Herdr responsive switch menu on a phone"
loading="lazy"
/>
<figcaption>responsive switch menu</figcaption>
</figure>
<p class="mobile-shout">
screenshots taken with
<a href="https://getmoshi.app/" target="_blank" rel="noopener">moshi</a>
❤️ on iphone
</p>
</div>
</div>
</section>
<section class="section api-section">
<div class="api-copy">
<p class="section-kicker">Runtime surface</p>
<h2>The UI is also a control surface.</h2>
<p>
Herdr exposes workspace, tab, pane, output, and wait
operations through a CLI and newline-delimited JSON
socket API. Agents can operate their own workspace
instead of asking you to shuffle terminals by hand.
</p>
<div class="inline-links">
<a href="/docs/cli-reference/">CLI reference →</a>
<a href="/docs/socket-api/">Socket API →</a>
<a href="/docs/agent-skill/">Agent skill →</a>
</div>
</div>
<div class="code-card" aria-label="Herdr CLI orchestration example">
<pre><code><span class="comment"># create workspace structure</span>
<span class="cmd">herdr</span> workspace create <span class="flag">--cwd</span> <span class="str">~/project</span> <span class="flag">--label</span> <span class="str">api</span>
<span class="cmd">herdr</span> tab create <span class="flag">--label</span> <span class="str">logs</span>
<span class="comment"># split a pane and run work</span>
<span class="cmd">herdr</span> pane split <span class="str">1-1</span> <span class="flag">--direction</span> <span class="str">right</span>
<span class="cmd">herdr</span> pane run <span class="str">1-2</span> <span class="str">"just test"</span>
<span class="comment"># wait, inspect, and continue</span>
<span class="cmd">herdr</span> wait agent-status <span class="str">1-1</span> <span class="flag">--status</span> <span class="str">done</span>
<span class="cmd">herdr</span> pane read <span class="str">1-2</span> <span class="flag">--source</span> <span class="str">recent-unwrapped</span></code></pre>
</div>
</section>
<section class="section awareness-section">
<div class="section-heading">
<p class="section-kicker">Agent awareness</p>
<h2>Keep the herd in sight.</h2>
</div>
<div class="awareness-grid">
<article class="awareness-card">
<figure class="awareness-mock" role="img" aria-label="Herdr workspace sidebar showing state rollups">
<div class="mock-sidebar">
<div class="mock-sidebar-title">spaces</div>
<div class="mock-space active">
<span class="mock-dot dot-done"></span>
<div><strong>herdr</strong><small>master</small></div>
</div>
<div class="mock-space">
<span class="mock-dot dot-working"></span>
<div><strong>llm-proxy</strong><small>master</small></div>
</div>
<div class="mock-space">
<span class="mock-dot dot-blocked"></span>
<div><strong>docs-site</strong><small>docs/palette</small></div>
</div>
<div class="mock-space">
<span class="mock-dot dot-idle"></span>
<div><strong>qmp</strong><small>autoresearch/…</small></div>
</div>
<div class="mock-sidebar-spacer"></div>
</div>
</figure>
<h3>Workspace rollups</h3>
<p>
Each workspace rolls up to its most urgent agent
state, so the whole session is scannable.
</p>
</article>
<article class="awareness-card">
<figure class="awareness-mock" role="img" aria-label="Herdr agent list showing states">
<div class="mock-sidebar">
<div class="mock-agent-title"><span>agents</span><span>all</span></div>
<div class="mock-agent"><span></span><div><strong>doc</strong><small>idle · pi</small></div></div>
<div class="mock-agent working"><span class="braille-spinner"></span><div><strong>custom-row</strong><small>working · pi</small></div></div>
<div class="mock-agent blocked"><span></span><div><strong>llm-proxy</strong><small>blocked · claude</small></div></div>
<div class="mock-agent done"><span></span><div><strong>qmp</strong><small>done · codex</small></div></div>
<div class="mock-sidebar-spacer"></div>
</div>
</figure>
<h3>Agent list</h3>
<p>
See which agents are blocked, working, done, idle, or
unknown without opening every pane.
</p>
</article>
</div>
<div class="state-legend">
<span><i class="status-dot dot-blocked"></i>blocked</span>
<span><i class="status-dot dot-working"></i>working</span>
<span><i class="status-dot dot-done"></i>done</span>
<span><i class="status-dot dot-idle"></i>idle</span>
</div>
</section>
<section class="section integrations-section">
<div class="section-heading">
<p class="section-kicker">Integrations</p>
<h2>Bring your existing agents into the herd.</h2>
</div>
<div class="agent-grid" aria-label="Supported agents">
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/pi.svg')"></span><span>Pi</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/claude.svg')"></span><span>Claude Code</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/codex-mask.svg')"></span><span>Codex</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/droid.png')"></span><span>Droid</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/amp.svg')"></span><span>Amp</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/opencode.svg')"></span><span>OpenCode</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/grok.svg')"></span><span>Grok CLI</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/hermes.svg')"></span><span>Hermes</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/cursor.svg')"></span><span>Cursor</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/antigravity.svg')"></span><span>Antigravity</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/kimi.svg')"></span><span>Kimi</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/kiro-mask.svg')"></span><span>Kiro</span></div>
<div class="agent-card"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/github-copilot.svg')"></span><span>Copilot</span></div>
<div class="agent-card agent-more"><span class="agent-icon" style="--agent-icon: url('/assets/agent-icons/herdr-mask.svg')"></span><span>more soon</span></div>
</div>
<p class="integration-note">
Any terminal agent works in Herdr. Use the Herdr API to add
richer state, orchestration, and custom workflows;
<a href="/docs/integrations/">see example integrations</a>
or build your own for anything.
</p>
</section>
<section class="final-cta">
<p class="section-kicker">Start the herd</p>
<h2>Install Herdr, run two agents, detach once.</h2>
<p>
The value shows up the first time the herd keeps running
after your terminal disappears.
</p>
<div class="hero-actions center">
<a class="button button-primary" href="/docs/install/"
>Install Herdr</a
>
<a class="button button-secondary" href="/docs/quick-start/"
>Quick start</a
>
</div>
</section>
</main>
<footer class="footer">
<a class="brand" href="/" aria-label="Herdr home">
<span class="brand-logo" aria-hidden="true"></span>
<span>herdr</span>
</a>
<div>
<a href="/compare/">Compare</a>
<a href="/docs/">Docs</a>
<a href="/docs/configuration/">Configuration</a>
<a href="/docs/socket-api/">API</a>
<a href="https://github.com/ogulcancelik/herdr/releases"
>Releases</a
>
<a href="mailto:hey@herdr.dev">hey@herdr.dev</a>
</div>
</footer>
<div class="logo-menu" id="logo-menu" hidden>
<a href="/assets/logo.svg" download="herdr-logo.svg">Download SVG</a>
<a href="/assets/logo.png" download="herdr-logo.png">Download PNG</a>
<button type="button" id="copy-logo-url">Copy SVG URL</button>
</div>
<div class="theme-hint" id="theme-hint" title="Press / or t to switch theme">
<span class="theme-hint-dot"></span>
<span class="theme-hint-label" id="theme-hint-label">light</span>
<span class="theme-hint-key">[/]</span>
</div>
<div class="theme-overlay" id="theme-overlay" hidden>
<div class="theme-overlay-panel" role="dialog" aria-label="Theme switcher" aria-modal="true">
<div class="theme-overlay-title">settings</div>
<div class="theme-overlay-tabs">
<span class="active">theme</span>
</div>
<div class="theme-overlay-list" id="theme-overlay-list" role="listbox" aria-label="Themes">
<div class="theme-sep"><span>dark</span></div>
<button type="button" role="option" data-value="catppuccin">catppuccin</button>
<button type="button" role="option" data-value="terminal">terminal</button>
<button type="button" role="option" data-value="tokyo-night">tokyo night</button>
<button type="button" role="option" data-value="dracula">dracula</button>
<button type="button" role="option" data-value="nord">nord</button>
<button type="button" role="option" data-value="gruvbox">gruvbox</button>
<button type="button" role="option" data-value="one-dark">one dark</button>
<button type="button" role="option" data-value="solarized">solarized</button>
<button type="button" role="option" data-value="kanagawa">kanagawa</button>
<button type="button" role="option" data-value="rose-pine">rose pine</button>
<button type="button" role="option" data-value="vesper">vesper</button>
<div class="theme-sep"><span>light</span></div>
<button type="button" role="option" data-value="catppuccin-latte">catppuccin latte</button>
<button type="button" role="option" data-value="tokyo-night-day">tokyo day</button>
<button type="button" role="option" data-value="gruvbox-light">gruvbox light</button>
<button type="button" role="option" data-value="one-light">one light</button>
<button type="button" role="option" data-value="solarized-light">solarized light</button>
<button type="button" role="option" data-value="kanagawa-lotus">kanagawa lotus</button>
<button type="button" role="option" data-value="rose-pine-dawn">rose pine dawn</button>
</div>
<div class="theme-overlay-footer">
<span class="theme-overlay-hints"><span class="key">↑↓</span> select</span>
<span class="theme-overlay-actions"><span class="theme-apply-btn">↵ apply</span><button class="theme-close-btn" type="button" id="theme-close-btn">esc close</button></span>
</div>
</div>
</div>
<script>
(function () {
var overlay = document.getElementById("theme-overlay");
var list = document.getElementById("theme-overlay-list");
var hintLabel = document.getElementById("theme-hint-label");
if (!overlay || !list) return;
var options = Array.prototype.slice.call(list.querySelectorAll("[role='option']"));
var media = window.matchMedia("(prefers-color-scheme: dark)");
var saved = localStorage.getItem("herdr-palette") || "";
var committed = saved || defaultPalette();
function defaultPalette() {
return media.matches ? "tokyo-night" : "tokyo-night-day";
}
function setPalette(value) {
document.documentElement.setAttribute("data-palette", value || defaultPalette());
}
function updateUI(value) {
var activeValue = value || defaultPalette();
options.forEach(function (opt) {
var selected = opt.dataset.value === activeValue;
opt.setAttribute("aria-selected", String(selected));
});
var active = options.find(function (o) { return o.dataset.value === activeValue; });
if (hintLabel && active) hintLabel.textContent = active.textContent.trim();
}
function openOverlay() {
overlay.hidden = false;
document.body.style.overflow = "hidden";
committed = localStorage.getItem("herdr-palette") || defaultPalette();
updateUI(committed);
var active = list.querySelector("[aria-selected='true']") || options[0];
if (active) active.focus();
}
function closeOverlay() {
overlay.hidden = true;
document.body.style.overflow = "";
}
function toggleOverlay() {
if (overlay.hidden) openOverlay();
else closeOverlay();
}
function preview(index) {
if (index < 0 || index >= options.length) return;
setPalette(options[index].dataset.value);
updateUI(options[index].dataset.value);
options[index].focus();
}
function commit(value) {
setPalette(value);
localStorage.setItem("herdr-palette", value);
updateUI(value);
closeOverlay();
}
function revert() {
setPalette(committed);
updateUI(committed);
closeOverlay();
}
media.addEventListener("change", function () {
if (!localStorage.getItem("herdr-palette")) {
setPalette("");
updateUI("");
}
});
options.forEach(function (opt, idx) {
opt.addEventListener("click", function () {
commit(opt.dataset.value);
});
opt.addEventListener("mouseenter", function () {
preview(idx);
});
});
document.addEventListener("keydown", function (e) {
if ((e.key === "t" || e.key === "/") && !e.ctrlKey && !e.metaKey && !e.altKey) {
var tag = document.activeElement && document.activeElement.tagName;
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return;
e.preventDefault();
toggleOverlay();
return;
}
if (overlay.hidden) return;
var current = document.activeElement;
var idx = options.indexOf(current);
if (e.key === "ArrowDown") {
e.preventDefault();
var nextIdx = idx >= 0 ? Math.min(options.length - 1, idx + 1) : 0;
preview(nextIdx);
} else if (e.key === "ArrowUp") {
e.preventDefault();
var prevIdx = idx >= 0 ? Math.max(0, idx - 1) : options.length - 1;
preview(prevIdx);
} else if (e.key === "Enter" && idx >= 0) {
e.preventDefault();
commit(options[idx].dataset.value);
} else if (e.key === "Escape") {
e.preventDefault();
revert();
}
});
var themeHint = document.getElementById("theme-hint");
if (localStorage.getItem("herdr-theme-hint-seen") === "1") {
themeHint.classList.add("is-seen");
}
themeHint.addEventListener("mouseenter", function () {
localStorage.setItem("herdr-theme-hint-seen", "1");
themeHint.classList.add("is-seen");
}, { once: true });
themeHint.addEventListener("click", toggleOverlay);
document.getElementById("theme-close-btn").addEventListener("click", revert);
setPalette(saved);
updateUI(saved);
})();
(function () {
var menu = document.getElementById("logo-menu");
var copyButton = document.getElementById("copy-logo-url");
var logos = document.querySelectorAll(".brand-logo");
if (!menu || !logos.length) return;
function hideMenu() {
menu.hidden = true;
}
function showMenu(event) {
event.preventDefault();
menu.hidden = false;
var menuWidth = menu.offsetWidth;
var menuHeight = menu.offsetHeight;
var left = Math.min(event.clientX, window.innerWidth - menuWidth - 12);
var top = Math.min(event.clientY, window.innerHeight - menuHeight - 12);
menu.style.left = Math.max(12, left) + "px";
menu.style.top = Math.max(12, top) + "px";
}
logos.forEach(function (logo) {
logo.addEventListener("contextmenu", showMenu);
});
document.addEventListener("click", function (event) {
if (!menu.contains(event.target)) hideMenu();
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape") hideMenu();
});
window.addEventListener("scroll", hideMenu, { passive: true });
window.addEventListener("resize", hideMenu);
if (copyButton) {
copyButton.addEventListener("click", async function () {
var url = new URL("/assets/logo.svg", window.location.href).href;
try {
await navigator.clipboard.writeText(url);
copyButton.textContent = "Copied";
setTimeout(function () {
copyButton.textContent = "Copy SVG URL";
}, 1500);
} catch (error) {
window.prompt("Copy logo URL", url);
}
});
}
})();
(function () {
var reduceMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)",
).matches;
if (reduceMotion) return;
document.querySelectorAll(".logo-marquee").forEach(function (marquee) {
var track = marquee.querySelector(".logo-track");
if (!track || !track.getAnimations) return;
function setPlaybackRate(rate) {
var animation = track.getAnimations().find(function (candidate) {
return candidate.animationName === "logo-marquee";
});
if (!animation) return;
if (animation.updatePlaybackRate) {
animation.updatePlaybackRate(rate);
} else {
animation.playbackRate = rate;
}
}
marquee.addEventListener("mouseenter", function () {
setPlaybackRate(0.6);
});
marquee.addEventListener("mouseleave", function () {
setPlaybackRate(1);
});
});
})();
(function () {
var copyButton = document.getElementById("copy-btn");
var command = document.getElementById("install-cmd");
var methods = Array.prototype.slice.call(
document.querySelectorAll(".install-method"),
);
if (!copyButton || !command || methods.length === 0) return;
methods.forEach(function (method) {
method.addEventListener("click", function () {
methods.forEach(function (entry) {
var active = entry === method;
entry.classList.toggle("is-active", active);
entry.setAttribute("aria-pressed", String(active));
});
command.textContent = method.dataset.command;
command.classList.toggle(
"is-compact",
method.dataset.size === "compact",
);
copyButton.textContent = "Copy";
});
});
copyButton.addEventListener("click", async function () {
try {
await navigator.clipboard.writeText(
command.textContent.trim(),
);
copyButton.textContent = "Copied";
setTimeout(function () {
copyButton.textContent = "Copy";
}, 1500);
} catch (error) {
copyButton.textContent = "Select";
}
});
})();
(function () {
var frames = ["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];
var els = document.querySelectorAll(".braille-spinner");
if (!els.length) return;
var states = Array.prototype.map.call(els, function () { return 0; });
els.forEach(function (el, idx) {
el.textContent = frames[0];
});
setInterval(function () {
els.forEach(function (el, idx) {
states[idx] = (states[idx] + 1) % frames.length;
el.textContent = frames[states[idx]];
});
}, 80);
})();
</script>
</body>
</html>