1349 lines
34 KiB
HTML
1349 lines
34 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>byre</title>
|
||
<meta name="description" content="Run many coding agents in parallel on one Mac, each on its own branch, with a lead agent that keeps track of them for you, and drive them from every Mac you use.">
|
||
<link rel="icon" href="/icon.png" type="image/png" sizes="180x180">
|
||
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
||
<link rel="apple-touch-icon" href="/icon.png">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://byre.run/">
|
||
<meta property="og:site_name" content="byre">
|
||
<meta property="og:title" content="byre: a crew of coding agents, on all your Macs">
|
||
<meta property="og:description" content="Run Claude Code, Codex and Antigravity side by side, each on its own branch, with a lead agent that tells you what needs you.">
|
||
<meta property="og:image" content="https://byre.run/card.png">
|
||
<meta property="og:image:width" content="1200">
|
||
<meta property="og:image:height" content="630">
|
||
<meta property="og:image:alt" content="byre: A crew of coding agents, on all your Macs.">
|
||
<meta name="twitter:card" content="summary_large_image">
|
||
<style>
|
||
@font-face {
|
||
font-family: "Atkinson Hyperlegible Mono";
|
||
font-weight: 200 800;
|
||
src: url("/fonts/atkinson-hyperlegible-mono-latin-wght-normal.woff2") format("woff2");
|
||
}
|
||
@font-face {
|
||
font-family: "Atkinson Hyperlegible Mono";
|
||
font-weight: 200 800;
|
||
src: url("/fonts/atkinson-hyperlegible-mono-latin-ext-wght-normal.woff2") format("woff2");
|
||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||
}
|
||
:root {
|
||
--bg: #fbfbfa;
|
||
--surface: #f2f3f5;
|
||
--border: #d6d9de;
|
||
--text: #16181b;
|
||
--muted: #4a5260;
|
||
--accent: #1f55d6;
|
||
--accent-tint: #e7edfb;
|
||
--blue: #3d7dff;
|
||
--red: #ff3b4e;
|
||
--orange: #ff9500;
|
||
--green: #34d058;
|
||
--purple: #b05cff;
|
||
--cyan: #00d5f0;
|
||
--on-color: #15171a;
|
||
--tint: 7%;
|
||
}
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--bg: #15171a;
|
||
--surface: #1c1f23;
|
||
--border: #353b43;
|
||
--text: #eceff3;
|
||
--muted: #a9b1bc;
|
||
--accent: #8ab4ff;
|
||
--accent-tint: #1e2a40;
|
||
--tint: 10%;
|
||
}
|
||
}
|
||
* {
|
||
box-sizing: border-box;
|
||
}
|
||
body {
|
||
margin: 0;
|
||
background: var(--bg);
|
||
color: var(--text);
|
||
font: 16px/1.6 "Atkinson Hyperlegible Mono", ui-monospace, monospace;
|
||
border-top: 6px solid;
|
||
border-image: linear-gradient(90deg, var(--red), var(--orange), var(--green), var(--cyan), var(--blue), var(--purple)) 1;
|
||
}
|
||
main {
|
||
max-width: 960px;
|
||
margin: 0 auto;
|
||
padding: 64px 16px;
|
||
}
|
||
a {
|
||
color: var(--accent);
|
||
}
|
||
header {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 24px;
|
||
padding-bottom: 56px;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
header img {
|
||
width: 72px;
|
||
height: 72px;
|
||
border-radius: 16px;
|
||
}
|
||
h1 {
|
||
margin: 0;
|
||
font-size: clamp(32px, 6vw, 52px);
|
||
line-height: 1.15;
|
||
font-weight: 700;
|
||
letter-spacing: -0.02em;
|
||
}
|
||
h1 span {
|
||
background: linear-gradient(transparent 72%, color-mix(in srgb, var(--blue) 30%, transparent) 72%);
|
||
}
|
||
.lede {
|
||
margin: 0;
|
||
max-width: 44em;
|
||
color: var(--muted);
|
||
font-size: 18px;
|
||
}
|
||
.download {
|
||
display: inline-block;
|
||
padding: 12px 22px;
|
||
border-radius: 8px;
|
||
background: var(--accent);
|
||
color: var(--bg);
|
||
font-weight: 700;
|
||
text-decoration: none;
|
||
}
|
||
.download:hover {
|
||
opacity: 0.9;
|
||
}
|
||
h2 {
|
||
margin: 56px 0 24px;
|
||
font-size: 22px;
|
||
}
|
||
.features {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 16px;
|
||
margin: 0;
|
||
padding: 0;
|
||
list-style: none;
|
||
}
|
||
.features > li {
|
||
--c: var(--blue);
|
||
padding: 20px;
|
||
border: 1px solid var(--border);
|
||
border-top: 4px solid var(--c);
|
||
border-radius: 10px;
|
||
background: color-mix(in srgb, var(--c) var(--tint), var(--surface));
|
||
}
|
||
.features .wide {
|
||
grid-column: span 2;
|
||
}
|
||
.features .hero {
|
||
grid-column: 1 / -1;
|
||
padding: 28px;
|
||
}
|
||
.features h3 {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 10px;
|
||
margin: 0 0 8px;
|
||
font-size: 16px;
|
||
}
|
||
.features h3::before {
|
||
content: "";
|
||
flex: none;
|
||
width: 10px;
|
||
height: 10px;
|
||
margin-top: calc(0.8em - 5px);
|
||
border-radius: 50%;
|
||
background: var(--c);
|
||
}
|
||
.features .hero h3 {
|
||
font-size: 22px;
|
||
}
|
||
.features summary p {
|
||
margin: 0;
|
||
color: var(--muted);
|
||
font-size: 14px;
|
||
}
|
||
.features .hero summary p {
|
||
max-width: 52em;
|
||
font-size: 16px;
|
||
}
|
||
.features summary {
|
||
position: relative;
|
||
display: block;
|
||
padding-right: 32px;
|
||
cursor: pointer;
|
||
list-style: none;
|
||
}
|
||
.features summary::-webkit-details-marker {
|
||
display: none;
|
||
}
|
||
.more {
|
||
position: absolute;
|
||
top: 4px;
|
||
right: 4px;
|
||
width: 10px;
|
||
height: 10px;
|
||
border-right: 2px solid var(--muted);
|
||
border-bottom: 2px solid var(--muted);
|
||
transform: rotate(45deg);
|
||
transition: transform 250ms cubic-bezier(0.65, 0, 0.35, 1), border-color 150ms;
|
||
}
|
||
.features summary:hover .more {
|
||
border-color: var(--c);
|
||
}
|
||
details[open] .more {
|
||
transform: translateY(5px) rotate(225deg);
|
||
}
|
||
.features > li:has(details[open]) {
|
||
grid-column: 1 / -1;
|
||
}
|
||
::view-transition-group(*) {
|
||
overflow: hidden;
|
||
border-radius: 10px;
|
||
animation-duration: 300ms;
|
||
animation-timing-function: cubic-bezier(0.65, 0, 0.35, 1);
|
||
}
|
||
::view-transition-old(*),
|
||
::view-transition-new(*) {
|
||
height: 100%;
|
||
object-fit: none;
|
||
object-position: left top;
|
||
}
|
||
.detail {
|
||
margin-top: 24px;
|
||
padding-top: 24px;
|
||
border-top: 1px solid color-mix(in srgb, var(--c) 30%, var(--border));
|
||
}
|
||
.points {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 20px;
|
||
margin: 28px 0 0;
|
||
padding: 0;
|
||
list-style: none;
|
||
color: var(--muted);
|
||
font-size: 14px;
|
||
text-wrap: pretty;
|
||
}
|
||
.points strong {
|
||
display: block;
|
||
margin-bottom: 4px;
|
||
color: var(--text);
|
||
}
|
||
.fig {
|
||
font-size: 13px;
|
||
line-height: 1.5;
|
||
}
|
||
.fig ul {
|
||
margin: 0;
|
||
padding: 0;
|
||
list-style: none;
|
||
}
|
||
.fig i {
|
||
display: inline-block;
|
||
flex: none;
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background: var(--c);
|
||
}
|
||
.fig .live {
|
||
animation: pulse 1.6s ease-in-out infinite;
|
||
}
|
||
.fig b {
|
||
font-weight: 700;
|
||
}
|
||
.muted {
|
||
color: var(--muted);
|
||
}
|
||
.split {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 20px;
|
||
align-items: start;
|
||
}
|
||
.stack {
|
||
display: grid;
|
||
gap: 12px;
|
||
}
|
||
.win {
|
||
overflow: hidden;
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
background: var(--bg);
|
||
}
|
||
.bar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
padding: 6px 10px;
|
||
border-bottom: 1px solid var(--border);
|
||
background: var(--surface);
|
||
color: var(--muted);
|
||
font-size: 12px;
|
||
}
|
||
.fig .bar i {
|
||
width: 7px;
|
||
height: 7px;
|
||
background: var(--border);
|
||
}
|
||
.bar i:last-of-type {
|
||
margin-right: 6px;
|
||
}
|
||
.body {
|
||
padding: 12px;
|
||
}
|
||
.row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 6px 0;
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
.row:first-child {
|
||
border-top: 0;
|
||
}
|
||
.row .end {
|
||
margin-left: auto;
|
||
color: var(--muted);
|
||
}
|
||
.chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 1px 8px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 999px;
|
||
background: var(--bg);
|
||
font-size: 12px;
|
||
white-space: nowrap;
|
||
}
|
||
.chip.on {
|
||
border-color: var(--c);
|
||
background: color-mix(in srgb, var(--c) 14%, var(--bg));
|
||
}
|
||
.btn {
|
||
display: inline-block;
|
||
padding: 4px 12px;
|
||
border-radius: 6px;
|
||
background: var(--c);
|
||
color: var(--on-color);
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
white-space: nowrap;
|
||
}
|
||
.btn.ghost {
|
||
border: 1px solid var(--border);
|
||
background: var(--bg);
|
||
color: var(--text);
|
||
}
|
||
.msg {
|
||
max-width: 88%;
|
||
margin-top: 8px;
|
||
padding: 8px 10px;
|
||
border-radius: 8px;
|
||
background: var(--surface);
|
||
}
|
||
.msg:first-child {
|
||
margin-top: 0;
|
||
}
|
||
.msg.you {
|
||
margin-left: auto;
|
||
background: color-mix(in srgb, var(--c) 16%, var(--bg));
|
||
}
|
||
.msg .row {
|
||
padding: 3px 0;
|
||
border: 0;
|
||
}
|
||
.caption {
|
||
margin-top: 8px;
|
||
color: var(--muted);
|
||
font-size: 12px;
|
||
text-align: center;
|
||
}
|
||
.wires {
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: visible;
|
||
}
|
||
.wires path {
|
||
fill: none;
|
||
stroke: var(--c);
|
||
stroke-width: 2;
|
||
stroke-dasharray: 6 6;
|
||
vector-effect: non-scaling-stroke;
|
||
animation: flow 1s linear infinite;
|
||
}
|
||
.wires .off {
|
||
stroke: var(--border);
|
||
animation: none;
|
||
}
|
||
.diagram {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 5fr) minmax(48px, 2fr) minmax(0, 5fr);
|
||
}
|
||
.server {
|
||
align-self: center;
|
||
padding: 16px;
|
||
box-shadow: 0 0 0 4px color-mix(in srgb, var(--c) 18%, transparent);
|
||
}
|
||
.server .label {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 6px;
|
||
font-weight: 700;
|
||
}
|
||
.server .label span {
|
||
color: var(--muted);
|
||
font-weight: 400;
|
||
}
|
||
.server .row:first-child {
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
.server .red .end {
|
||
color: var(--text);
|
||
font-weight: 700;
|
||
}
|
||
.clients {
|
||
display: grid;
|
||
grid-template-rows: repeat(3, 1fr);
|
||
gap: 12px;
|
||
}
|
||
.client .rows {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 10px;
|
||
color: var(--muted);
|
||
font-size: 12px;
|
||
}
|
||
.rows span {
|
||
flex: 1;
|
||
height: 8px;
|
||
border-radius: 4px;
|
||
background: var(--c);
|
||
}
|
||
.client.asleep {
|
||
opacity: 0.45;
|
||
}
|
||
.servers .row.on {
|
||
margin: 0 -12px;
|
||
padding: 6px 12px;
|
||
background: color-mix(in srgb, var(--c) 12%, var(--bg));
|
||
}
|
||
.projects {
|
||
padding: 4px 0 6px 18px;
|
||
color: var(--muted);
|
||
}
|
||
.projects li::before {
|
||
content: "└ ";
|
||
color: var(--border);
|
||
}
|
||
.synced .body {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 6px;
|
||
}
|
||
.task .body {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
.task .name {
|
||
flex-basis: 100%;
|
||
font-weight: 700;
|
||
}
|
||
.option {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-top: 8px;
|
||
padding: 8px 10px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
}
|
||
.option::before {
|
||
content: "";
|
||
flex: none;
|
||
width: 12px;
|
||
height: 12px;
|
||
border: 2px solid var(--border);
|
||
border-radius: 50%;
|
||
}
|
||
.option.on {
|
||
border-color: var(--c);
|
||
background: color-mix(in srgb, var(--c) 10%, var(--bg));
|
||
}
|
||
.option.on::before {
|
||
border-color: var(--c);
|
||
background: radial-gradient(var(--c) 40%, transparent 45%);
|
||
}
|
||
.option > span {
|
||
margin-left: auto;
|
||
}
|
||
.notif {
|
||
display: flex;
|
||
gap: 12px;
|
||
padding: 14px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 14px;
|
||
background: color-mix(in srgb, var(--surface) 80%, var(--bg));
|
||
box-shadow: 0 6px 24px color-mix(in srgb, var(--text) 10%, transparent);
|
||
}
|
||
.notif .app {
|
||
flex: none;
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 8px;
|
||
background: linear-gradient(135deg, var(--red), var(--orange), var(--purple));
|
||
}
|
||
.flow {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-bottom: 16px;
|
||
}
|
||
.flow .arrow {
|
||
color: var(--muted);
|
||
}
|
||
.finding {
|
||
display: grid;
|
||
grid-template-columns: auto 1fr auto;
|
||
align-items: center;
|
||
gap: 6px 10px;
|
||
padding: 10px 0;
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
.finding:first-child {
|
||
border-top: 0;
|
||
}
|
||
.finding .reply {
|
||
grid-column: 2 / -1;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: 8px;
|
||
color: var(--muted);
|
||
}
|
||
.squash {
|
||
align-items: center;
|
||
}
|
||
.ready .body {
|
||
display: grid;
|
||
justify-items: start;
|
||
gap: 8px;
|
||
}
|
||
.graph svg {
|
||
display: block;
|
||
width: 100%;
|
||
}
|
||
.graph path {
|
||
fill: none;
|
||
stroke-width: 2;
|
||
}
|
||
.graph .line {
|
||
stroke: var(--border);
|
||
}
|
||
.graph .branch {
|
||
stroke: var(--c);
|
||
stroke-dasharray: 5 5;
|
||
animation: flow 1s linear infinite;
|
||
}
|
||
.graph .old {
|
||
fill: var(--border);
|
||
}
|
||
.graph .turn {
|
||
fill: var(--bg);
|
||
stroke: var(--muted);
|
||
stroke-width: 1.5;
|
||
}
|
||
.graph .new {
|
||
fill: var(--c);
|
||
stroke: color-mix(in srgb, var(--c) 30%, transparent);
|
||
stroke-width: 8;
|
||
}
|
||
.legend {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
margin-top: 6px;
|
||
color: var(--muted);
|
||
font-size: 12px;
|
||
}
|
||
.legend b {
|
||
color: var(--text);
|
||
}
|
||
.timeline {
|
||
position: relative;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
padding: 0 4%;
|
||
}
|
||
.timeline::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 4%;
|
||
right: 4%;
|
||
border-top: 2px solid var(--border);
|
||
}
|
||
.node {
|
||
position: relative;
|
||
display: grid;
|
||
place-items: center;
|
||
width: 36px;
|
||
height: 36px;
|
||
border: 2px solid var(--border);
|
||
border-radius: 50%;
|
||
background: var(--bg);
|
||
font-size: 12px;
|
||
}
|
||
.node.on {
|
||
border-color: var(--c);
|
||
background: color-mix(in srgb, var(--c) 18%, var(--bg));
|
||
font-weight: 700;
|
||
}
|
||
.fork {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
.fork::before {
|
||
content: "";
|
||
height: 28px;
|
||
border-left: 2px dashed var(--c);
|
||
}
|
||
.fork .win {
|
||
width: min(100%, 380px);
|
||
}
|
||
.snaps .split {
|
||
align-items: center;
|
||
}
|
||
.diff .row {
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.plus {
|
||
color: var(--green);
|
||
}
|
||
.minus {
|
||
color: var(--red);
|
||
}
|
||
.pipeline {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 3fr) minmax(32px, 1fr) minmax(0, 3fr) minmax(32px, 1fr) minmax(0, 3fr);
|
||
align-items: stretch;
|
||
}
|
||
.pipeline .stack {
|
||
grid-template-rows: repeat(3, 1fr);
|
||
}
|
||
.stage {
|
||
align-self: center;
|
||
padding: 10px 12px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
background: var(--bg);
|
||
}
|
||
.pipeline .stack .stage {
|
||
align-self: stretch;
|
||
}
|
||
.stage .muted {
|
||
display: block;
|
||
font-size: 12px;
|
||
}
|
||
.screen {
|
||
position: relative;
|
||
}
|
||
.screen .body {
|
||
display: grid;
|
||
gap: 10px;
|
||
}
|
||
.screen .title {
|
||
line-height: 20px;
|
||
}
|
||
.field {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
height: 34px;
|
||
padding: 0 10px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
}
|
||
.typed {
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
}
|
||
.email {
|
||
width: 15ch;
|
||
animation: type-email 8s infinite;
|
||
}
|
||
.password {
|
||
width: 8ch;
|
||
animation: type-password 8s infinite;
|
||
}
|
||
.screen .btn {
|
||
justify-self: end;
|
||
height: 28px;
|
||
line-height: 20px;
|
||
animation: press 8s infinite;
|
||
}
|
||
.toast {
|
||
position: absolute;
|
||
left: 12px;
|
||
bottom: 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 4px 10px;
|
||
border: 1px solid var(--c);
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--c) 16%, var(--bg));
|
||
font-size: 12px;
|
||
animation: toast 8s infinite;
|
||
}
|
||
.cursor {
|
||
position: absolute;
|
||
top: 170px;
|
||
left: calc(100% - 56px);
|
||
display: flex;
|
||
align-items: flex-start;
|
||
pointer-events: none;
|
||
animation: steer 8s infinite;
|
||
}
|
||
.cursor svg {
|
||
width: 18px;
|
||
height: 18px;
|
||
fill: var(--c);
|
||
stroke: var(--bg);
|
||
stroke-width: 1;
|
||
}
|
||
.cursor .tag {
|
||
margin: 14px 0 0 -2px;
|
||
padding: 0 6px;
|
||
border-radius: 4px;
|
||
background: var(--c);
|
||
color: var(--on-color);
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
}
|
||
.log .row:nth-child(1) {
|
||
animation: log-1 8s infinite;
|
||
}
|
||
.log .row:nth-child(2) {
|
||
animation: log-2 8s infinite;
|
||
}
|
||
.log .row:nth-child(3) {
|
||
animation: log-3 8s infinite;
|
||
}
|
||
.log .row:nth-child(4) {
|
||
animation: log-4 8s infinite;
|
||
}
|
||
@keyframes steer {
|
||
0%,
|
||
4% {
|
||
top: 200px;
|
||
left: 25%;
|
||
opacity: 0;
|
||
}
|
||
12%,
|
||
32% {
|
||
top: 84px;
|
||
left: 55%;
|
||
opacity: 1;
|
||
}
|
||
40%,
|
||
52% {
|
||
top: 128px;
|
||
left: 55%;
|
||
}
|
||
60%,
|
||
64% {
|
||
top: 170px;
|
||
left: calc(100% - 56px);
|
||
transform: none;
|
||
}
|
||
62% {
|
||
transform: scale(0.85);
|
||
}
|
||
92% {
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
top: 170px;
|
||
left: calc(100% - 56px);
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes type-email {
|
||
0%,
|
||
12% {
|
||
width: 0;
|
||
animation-timing-function: steps(15);
|
||
}
|
||
30%,
|
||
92% {
|
||
width: 15ch;
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes type-password {
|
||
0%,
|
||
40% {
|
||
width: 0;
|
||
animation-timing-function: steps(8);
|
||
}
|
||
50%,
|
||
92% {
|
||
width: 8ch;
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes press {
|
||
0%,
|
||
61%,
|
||
64%,
|
||
100% {
|
||
transform: none;
|
||
}
|
||
62% {
|
||
transform: scale(0.92);
|
||
}
|
||
}
|
||
@keyframes toast {
|
||
0%,
|
||
64% {
|
||
opacity: 0;
|
||
transform: translateY(6px);
|
||
}
|
||
68%,
|
||
92% {
|
||
opacity: 1;
|
||
transform: none;
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes log-1 {
|
||
0%,
|
||
6% {
|
||
opacity: 0;
|
||
}
|
||
8%,
|
||
92% {
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes log-2 {
|
||
0%,
|
||
30% {
|
||
opacity: 0;
|
||
}
|
||
32%,
|
||
92% {
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes log-3 {
|
||
0%,
|
||
50% {
|
||
opacity: 0;
|
||
}
|
||
52%,
|
||
92% {
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes log-4 {
|
||
0%,
|
||
66% {
|
||
opacity: 0;
|
||
}
|
||
68%,
|
||
92% {
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes pulse {
|
||
50% {
|
||
opacity: 0.3;
|
||
}
|
||
}
|
||
@keyframes flow {
|
||
to {
|
||
stroke-dashoffset: -12;
|
||
}
|
||
}
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.fig .live,
|
||
.wires path,
|
||
.graph .branch,
|
||
.typed,
|
||
.screen .btn,
|
||
.toast,
|
||
.cursor,
|
||
.log .row {
|
||
animation: none;
|
||
}
|
||
.more {
|
||
transition: none;
|
||
}
|
||
::view-transition-group(*),
|
||
::view-transition-old(*),
|
||
::view-transition-new(*) {
|
||
animation: none;
|
||
}
|
||
}
|
||
.features .red {
|
||
--c: var(--red);
|
||
}
|
||
.features .orange {
|
||
--c: var(--orange);
|
||
}
|
||
.features .green {
|
||
--c: var(--green);
|
||
}
|
||
.features .cyan {
|
||
--c: var(--cyan);
|
||
}
|
||
.features .purple {
|
||
--c: var(--purple);
|
||
}
|
||
.features .blue {
|
||
--c: var(--blue);
|
||
}
|
||
@media (max-width: 900px) {
|
||
.features {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
}
|
||
@media (max-width: 560px) {
|
||
h1 {
|
||
text-wrap: balance;
|
||
}
|
||
h1 br {
|
||
display: none;
|
||
}
|
||
.features {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
.features .wide {
|
||
grid-column: auto;
|
||
}
|
||
.split,
|
||
.diagram,
|
||
.pipeline {
|
||
grid-template-columns: 1fr;
|
||
gap: 16px;
|
||
}
|
||
.wires {
|
||
display: none;
|
||
}
|
||
.clients {
|
||
grid-template-rows: none;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 8px;
|
||
}
|
||
.client .bar i {
|
||
display: none;
|
||
}
|
||
.pipeline .stack {
|
||
grid-template-rows: none;
|
||
}
|
||
.points {
|
||
grid-template-columns: 1fr;
|
||
gap: 14px;
|
||
}
|
||
}
|
||
ol {
|
||
margin: 0;
|
||
padding-left: 24px;
|
||
max-width: 48em;
|
||
}
|
||
ol li + li {
|
||
margin-top: 12px;
|
||
}
|
||
ol li::marker {
|
||
color: var(--accent);
|
||
font-weight: 700;
|
||
}
|
||
footer {
|
||
margin-top: 72px;
|
||
padding-top: 24px;
|
||
border-top: 1px solid var(--border);
|
||
color: var(--muted);
|
||
font-size: 14px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<main>
|
||
<header>
|
||
<img src="/icon.svg" alt="">
|
||
<h1>A crew of coding agents, <br><span>on all your Macs.</span></h1>
|
||
<p class="lede">byre runs Claude Code, Codex and Antigravity side by side on one Mac, each on its own branch and worktree, with a lead agent that watches them all and tells you what needs you. Pick up from whichever Mac you're at.</p>
|
||
<a class="download" href="https://dl.byre.run/byre.dmg">Download for macOS</a>
|
||
</header>
|
||
|
||
<h2>What it does</h2>
|
||
<ul class="features">
|
||
|
||
<li class="hero"><details name="feature">
|
||
<summary><h3>One server, every Mac</h3><p>The agents run on one Mac that stays on, such as a Mac mini in a closet. Open byre on your laptop, your desk Mac, or all of them at once: each shows the same tasks, questions and transcripts live. Close the laptop and the agents keep working.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig diagram" aria-hidden="true">
|
||
<div class="win server">
|
||
<div class="label">Mac mini<span>in the closet</span></div>
|
||
<ul>
|
||
<li class="row green"><i class="live"></i>fix-login<span class="end">working</span></li>
|
||
<li class="row green"><i class="live"></i>website<span class="end">working</span></li>
|
||
<li class="row red"><i></i>deploy<span class="end">needs you</span></li>
|
||
<li class="row cyan"><i></i>search<span class="end">in review</span></li>
|
||
</ul>
|
||
</div>
|
||
<svg class="wires" viewBox="0 0 100 300" preserveAspectRatio="none">
|
||
<path d="M0 150 C50 150 50 50 100 50"/>
|
||
<path d="M0 150 L100 150"/>
|
||
<path class="off" d="M0 150 C50 150 50 250 100 250"/>
|
||
</svg>
|
||
<div class="clients">
|
||
<div class="win client"><div class="bar"><i></i><i></i><i></i>MacBook Air</div><div class="rows"><span class="green"></span><span class="green"></span><span class="red"></span><span class="cyan"></span></div></div>
|
||
<div class="win client"><div class="bar"><i></i><i></i><i></i>iMac</div><div class="rows"><span class="green"></span><span class="green"></span><span class="red"></span><span class="cyan"></span></div></div>
|
||
<div class="win client asleep"><div class="bar"><i></i><i></i><i></i>MacBook Pro</div><div class="rows">lid closed</div></div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Live on every screen.</strong> Answer a question on the laptop and it's gone from the iMac the same second.</li>
|
||
<li><strong>Close the lid.</strong> The crew lives on the server, so shut the laptop and come back to finished work.</li>
|
||
<li><strong>From anywhere.</strong> byre talks over Tailscale, so the closet Mac is one click from the coffee shop.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li class="wide purple"><details name="feature">
|
||
<summary><h3>Every server, every project</h3><p>Your servers sync through iCloud, so a new Mac finds them on first launch. Switch between servers in one window, each with as many projects as you like and its own color.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig split" aria-hidden="true">
|
||
<div class="win servers">
|
||
<div class="bar"><i></i><i></i><i></i>byre</div>
|
||
<div class="body">
|
||
<ul>
|
||
<li class="row on purple"><i></i><b>mac-mini</b><span class="end">3 projects</span></li>
|
||
</ul>
|
||
<ul class="projects">
|
||
<li>byre</li>
|
||
<li>website</li>
|
||
<li>infra</li>
|
||
</ul>
|
||
<ul>
|
||
<li class="row cyan"><i></i>studio<span class="end">2 projects</span></li>
|
||
<li class="row orange"><i></i>build-box<span class="end">5 projects</span></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div class="stack">
|
||
<div class="win synced"><div class="bar"><i></i><i></i><i></i>MacBook Air</div><div class="body"><span class="chip purple"><i></i>mac-mini</span><span class="chip cyan"><i></i>studio</span><span class="chip orange"><i></i>build-box</span></div></div>
|
||
<div class="win synced"><div class="bar"><i></i><i></i><i></i>new Mac Studio</div><div class="body"><span class="chip purple"><i></i>mac-mini</span><span class="chip cyan"><i></i>studio</span><span class="chip orange"><i></i>build-box</span></div></div>
|
||
</div>
|
||
<div class="caption">first launch, synced through iCloud</div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Already there.</strong> Servers sync through iCloud, so a new Mac finds them all on first launch.</li>
|
||
<li><strong>One window.</strong> Switch between every server and all of its projects without leaving it.</li>
|
||
<li><strong>Color-coded.</strong> Each server wears its own color, so you always know which one you're on.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li class="green"><details name="feature">
|
||
<summary><h3>Tasks</h3><p>Every task gets its own git worktree, branch and port block. Talk to its agent in a live transcript, even mid-turn.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig split" aria-hidden="true">
|
||
<div class="stack">
|
||
<div class="win task"><div class="body"><span class="name">fix-login</span><span class="chip">⎇ byre/fix-login</span><span class="chip">own worktree</span><span class="chip">ports 41000–41009</span></div></div>
|
||
<div class="win task"><div class="body"><span class="name">website</span><span class="chip">⎇ byre/website</span><span class="chip">own worktree</span><span class="chip">ports 41010–41019</span></div></div>
|
||
<div class="win task"><div class="body"><span class="name">search</span><span class="chip">⎇ byre/search</span><span class="chip">own worktree</span><span class="chip">ports 41020–41029</span></div></div>
|
||
</div>
|
||
<div class="win">
|
||
<div class="bar"><i></i><i></i><i></i>fix-login</div>
|
||
<div class="body">
|
||
<div class="msg">Moving sessions to the new table and copying the old rows across…</div>
|
||
<div class="msg you">keep the old column until the migration ships</div>
|
||
<div class="msg">Got it, I'll leave <b>legacy_id</b> in place and finish the copy.</div>
|
||
<div class="row"><i class="live"></i><span class="muted">working</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Isolated.</strong> Its own worktree, branch and ports, so parallel tasks never collide.</li>
|
||
<li><strong>Talk mid-turn.</strong> Message the agent while it works and it takes the note on board.</li>
|
||
<li><strong>As many as you like.</strong> Start another whenever an idea strikes; they all run at once.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li class="orange"><details name="feature">
|
||
<summary><h3>Lead agent</h3><p>One long-running agent watches every task, points you at what needs you, and starts, messages, merges or discards tasks when you ask.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig" aria-hidden="true">
|
||
<div class="win">
|
||
<div class="bar"><i></i><i></i><i></i>Lead</div>
|
||
<div class="body">
|
||
<div class="msg">Three tasks need you:
|
||
<ul>
|
||
<li class="row red"><i></i><b>deploy</b><span class="muted">has a question about cache lifetime</span></li>
|
||
<li class="row orange"><i></i><b>website</b><span class="muted">is ready to merge</span></li>
|
||
<li class="row cyan"><i></i><b>search</b><span class="muted">got two review findings</span></li>
|
||
</ul>
|
||
</div>
|
||
<div class="msg you">merge website, and start a task to add dark mode to the docs</div>
|
||
<div class="msg">Merging website now. Started <b>docs dark mode</b>; I'll tell you when it needs you.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Watches everything.</strong> Every task's turns, questions and reviews pass by the lead.</li>
|
||
<li><strong>Knows what needs you.</strong> It tells you which tasks are waiting on you, and why.</li>
|
||
<li><strong>Does the legwork.</strong> Ask it to start, message, merge or discard tasks, and it does.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li class="wide red"><details name="feature">
|
||
<summary><h3>Questions, not interruptions</h3><p>When an agent needs a decision, it lays out the options and recommends one. A notification brings you straight to it; pick an answer and the agent carries on.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig split" aria-hidden="true">
|
||
<div class="win">
|
||
<div class="bar"><i></i><i></i><i></i>deploy · question</div>
|
||
<div class="body">
|
||
<b>How long should the download page be cached?</b>
|
||
<div class="option">1 hour<span class="muted">fresh, more load</span></div>
|
||
<div class="option on">1 day<span class="chip on">recommended</span></div>
|
||
<div class="option">1 week<span class="muted">stale after a release</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="notif">
|
||
<div class="app"></div>
|
||
<div>
|
||
<b>byre · deploy</b>
|
||
<div class="muted">How long should the download page be cached?</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Options laid out.</strong> Every choice comes with what you get and what you give up.</li>
|
||
<li><strong>A recommendation.</strong> The agent always says which option it would pick, and why.</li>
|
||
<li><strong>Never miss one.</strong> A notification lands the moment a question does, a click away.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li class="wide cyan"><details name="feature">
|
||
<summary><h3>Cross-vendor reviews</h3><p>Every turn that changes files is reviewed by the other vendor's model. The agent fixes the findings it agrees with on its own and says why it skips the rest; you can overrule any of them with a click.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig" aria-hidden="true">
|
||
<div class="flow"><span class="chip">Claude Code turn</span><span class="arrow">→</span><span class="chip">snapshot 3</span><span class="arrow">→</span><span class="chip on">Codex review</span><span class="arrow">→</span><span class="chip">agent triages</span></div>
|
||
<div class="win">
|
||
<div class="bar"><i></i><i></i><i></i>search · review of snapshot 3</div>
|
||
<div class="body">
|
||
<div class="finding red"><i></i><b>Port block isn't freed when a task is discarded</b><span class="chip">medium</span><div class="reply"><span class="chip green on">fixing</span>Releasing it in the discard path.</div></div>
|
||
<div class="finding orange"><i></i><b>Rename cfg to config</b><span class="chip">low</span><div class="reply"><span class="chip">ignoring</span>Matches the surrounding code.<span class="btn ghost">Fix it anyway</span></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>A second opinion.</strong> Each turn that changes files is read by the other vendor's model.</li>
|
||
<li><strong>Triaged for you.</strong> The agent fixes what holds up and explains what it leaves.</li>
|
||
<li><strong>Your call.</strong> Overrule any finding it skipped with one click and it gets fixed.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li><details name="feature">
|
||
<summary><h3>One-click merge</h3><p>The agent merges main in and resolves conflicts, then byre squashes, pushes and closes the task.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig split squash" aria-hidden="true">
|
||
<div class="win ready">
|
||
<div class="bar"><i></i><i></i><i></i>avatars</div>
|
||
<div class="body">
|
||
<span class="chip on">ready to merge</span>
|
||
<b>Let people upload a profile photo</b>
|
||
<span class="muted">Photos are cropped to a square and resized, and initials show until one is set.</span>
|
||
<span class="btn">Merge</span>
|
||
</div>
|
||
</div>
|
||
<div class="graph">
|
||
<svg viewBox="0 0 300 120">
|
||
<path class="line" d="M10 95 H290"/>
|
||
<path class="branch" d="M60 95 C85 95 85 30 110 30 H210 C235 30 235 95 260 95"/>
|
||
<circle class="old" cx="30" cy="95" r="6"/>
|
||
<circle class="old" cx="60" cy="95" r="6"/>
|
||
<circle class="turn" cx="115" cy="30" r="4"/>
|
||
<circle class="turn" cx="138" cy="30" r="4"/>
|
||
<circle class="turn" cx="161" cy="30" r="4"/>
|
||
<circle class="turn" cx="184" cy="30" r="4"/>
|
||
<circle class="turn" cx="207" cy="30" r="4"/>
|
||
<circle class="new" cx="260" cy="95" r="9"/>
|
||
</svg>
|
||
<div class="legend"><span>5 turns on byre/avatars</span><span><b>1 commit on main</b></span></div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Conflicts handled.</strong> The agent merges main in and works through any conflicts.</li>
|
||
<li><strong>One clean commit.</strong> The whole task lands on main as a single squashed commit.</li>
|
||
<li><strong>Then it's done.</strong> byre pushes and closes the task, so your list stays short.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li class="green"><details name="feature">
|
||
<summary><h3>Snapshots and forks</h3><p>Step through a task's snapshots, diff any of them, and fork a new task from any one, conversation included.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig snaps" aria-hidden="true">
|
||
<div class="split">
|
||
<div>
|
||
<div class="timeline"><span class="node">#1</span><span class="node">#2</span><span class="node on">#3</span><span class="node">#4</span><span class="node">#5</span></div>
|
||
<div class="fork"><div class="win"><div class="bar"><i></i><i></i><i></i>new task</div><div class="body"><b>search: try SQLite FTS instead</b><div class="muted">forked from #3, conversation included</div></div></div></div>
|
||
</div>
|
||
<div class="win diff">
|
||
<div class="bar"><i></i><i></i><i></i>diff #3 → #5</div>
|
||
<div class="body">
|
||
<div class="row">index/build.go<span class="end"><span class="plus">+48</span> <span class="minus">−12</span></span></div>
|
||
<div class="row">index/query.go<span class="end"><span class="plus">+21</span> <span class="minus">−30</span></span></div>
|
||
<div class="row">docs/search.md<span class="end"><span class="plus">+9</span> <span class="minus">−2</span></span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Every step kept.</strong> Each turn that changes files leaves a snapshot behind it.</li>
|
||
<li><strong>Diff anything.</strong> Compare any two snapshots to see exactly what each turn did.</li>
|
||
<li><strong>Fork the past.</strong> Start a new task from any snapshot, conversation included.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li class="orange"><details name="feature">
|
||
<summary><h3>Teams and workflows</h3><p>Agents spawn subtasks or share a worktree as a team. Workflows chain stages with fan-out and fan-in.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig pipeline" aria-hidden="true">
|
||
<div class="stage"><b>plan</b><span class="muted">one agent</span></div>
|
||
<svg class="wires" viewBox="0 0 100 300" preserveAspectRatio="none">
|
||
<path d="M0 150 C50 150 50 50 100 50"/>
|
||
<path d="M0 150 L100 150"/>
|
||
<path d="M0 150 C50 150 50 250 100 250"/>
|
||
</svg>
|
||
<div class="stack">
|
||
<div class="stage"><b>build api</b><span class="muted">Claude Code</span></div>
|
||
<div class="stage"><b>build app</b><span class="muted">Codex</span></div>
|
||
<div class="stage"><b>write docs</b><span class="muted">Antigravity</span></div>
|
||
</div>
|
||
<svg class="wires" viewBox="0 0 100 300" preserveAspectRatio="none">
|
||
<path d="M0 50 C50 50 50 150 100 150"/>
|
||
<path d="M0 150 L100 150"/>
|
||
<path d="M0 250 C50 250 50 150 100 150"/>
|
||
</svg>
|
||
<div class="stage"><b>review</b><span class="muted">all three, together</span></div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Subtasks.</strong> An agent hands off pieces of work to new agents on their own branches.</li>
|
||
<li><strong>Teams.</strong> Several agents share one worktree and build the same change together.</li>
|
||
<li><strong>Workflows.</strong> Save a pipeline once: stages fan out, fan back in, and run again.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
<li class="purple"><details name="feature">
|
||
<summary><h3>Hands on your Macs</h3><p>Agents can see and drive the Mac byre runs on, and the Macs you have the app open on, when a task needs it.</p><span class="more"></span></summary>
|
||
<div class="detail">
|
||
<div class="fig hands" aria-hidden="true">
|
||
<div class="split">
|
||
<div class="win screen">
|
||
<div class="bar"><i></i><i></i><i></i>your app · on the iMac</div>
|
||
<div class="body">
|
||
<b class="title">Sign in</b>
|
||
<div class="field"><span class="muted">Email</span><span class="typed email">ada@example.com</span></div>
|
||
<div class="field"><span class="muted">Password</span><span class="typed password">••••••••</span></div>
|
||
<span class="btn">Sign in</span>
|
||
</div>
|
||
<div class="toast green"><i></i>Signed in as Ada</div>
|
||
<div class="cursor"><svg viewBox="0 0 16 16"><path d="M2 1 L2 14 L5.5 10.5 L8 15 L10 14 L7.5 9.5 L12.5 9.5 Z"/></svg><span class="tag">fix-login</span></div>
|
||
</div>
|
||
<div class="win">
|
||
<div class="bar"><i></i><i></i><i></i>fix-login</div>
|
||
<div class="body log">
|
||
<div class="row"><i></i>found the Sign in window</div>
|
||
<div class="row"><i></i>typed a test email</div>
|
||
<div class="row"><i></i>typed the password</div>
|
||
<div class="row green"><i></i>clicked Sign in: it works</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<ul class="points">
|
||
<li><strong>Sees the screen.</strong> Agents read screenshots and every window's controls.</li>
|
||
<li><strong>Drives the Mac.</strong> They click, type and browse to try what they just built.</li>
|
||
<li><strong>Your Macs too.</strong> Any Mac with byre's app open can lend the agents a hand.</li>
|
||
</ul>
|
||
</div>
|
||
</details></li>
|
||
|
||
</ul>
|
||
|
||
<h2>Getting started</h2>
|
||
<ol>
|
||
<li><a href="https://dl.byre.run/byre.dmg">Download byre</a> and click <strong>Run byre on this Mac</strong>.</li>
|
||
<li>Open it on every other Mac you own. Your crew is already there.</li>
|
||
</ol>
|
||
|
||
<footer>
|
||
byre is Apache 2.0 licensed. <a href="https://g.fc.run/ai/byre">Source</a> · <a href="https://g.fc.run/ai/byre/releases">Releases</a>
|
||
</footer>
|
||
</main>
|
||
<script>
|
||
for (const [i, el] of [...document.querySelectorAll(".features > li, main > h2, main > ol, footer")].entries()) {
|
||
el.style.viewTransitionName = `block-${i}`;
|
||
}
|
||
for (const summary of document.querySelectorAll(".features summary")) {
|
||
summary.addEventListener("click", (event) => {
|
||
event.preventDefault();
|
||
const details = summary.parentElement;
|
||
document.startViewTransition(() => {
|
||
details.open = !details.open;
|
||
});
|
||
});
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|