Skip to content
1,228 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Mission control: a place to ask g1t, shown and not on yet, with the actions under it1import { ArrowDownWideNarrow, ArrowRight, ArrowUpRight, Check, ChevronDown, ChevronRight, ListTree, Plus, Sparkles } from "lucide-react";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look2import { type ReactNode, useEffect, useState } from "react";
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)3import { Link, useFetcher, useLocation, useRouteLoaderData, useSearchParams } from "react-router";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look4
5import { trialClosed } from "../lib/trial";
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms6import { type ActivityGroup, type Verb, greetingFor, isAgent } from "../lib/mission";
7import {
8 BLOCKING,
9 type Fact,
10 type LandedRow,
11 type NeedRow,
12 type QuickAction,
13 REASON_LABEL,
14 type Reason,
15 type Sort,
16 type Tab,
17 type WaitingRow,
18 type Week,
19 type Who,
20 change,
21 dateLine,
22 parseSort,
23 parseTab,
24 signedPercent,
25 sortRows,
26 whyFor,
27} from "../lib/mission-control";
28import { cn } from "../lib/cn";
Money is written one way. A single formatter turns millionths of a dollar into dollars, rounding half up on whole micros rather than on a float, so the same sum reads the same on every page: under a cent reads <$0.01 on a total and exactly nothing is $0.00, while the statement's lines, a session's receipt, the price book and an agent's effort costs carry up to four places where the fraction of a cent is the point; the six formatters that each rounded their own way are gone. This month is the calendar month in UTC from its first day to today everywhere, and billing counts the month's not-yet-closed usage in any range that reaches into the current month, so the top bar's pill, Spend, Home and Usage ask for the same days and get the same figure; Home now reads the usage report the others read instead of adding up statements. Usage's pending sentence says what of that usage the close will charge after the discount and included usage, which the billing API returns as pending_charged_micros. A reconciliation test holds the pill, Spend, Home and Usage to one number for one month. The usage and billing guide says how amounts are written and what this month means.29import { microsOf, money } from "../lib/money";
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step30import { AgentComposer, type ComposerResult } from "./agent-composer";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look31import { AgentSetup } from "./agent-setup";
Inbox: a bell in the top bar opens it beside the page, and /inbox holds it all32import { InboxNeedsCard } from "./inbox";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look33import type { ShellData } from "./shell";
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms34import { useLiveRefresh } from "./agents";
35import { Unavailable } from "./mission";
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix36import { TokenUsagePanel } from "./token-usage";
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.37import { SubmitButton, TimeAgo } from "./ui";
38import { Avatar } from "./ui/avatar";
39import { Card } from "./ui/card";
Merge branch 'worktree-agent-ae1299e92e4462012'40import { Hint } from "./ui/hint";
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms41import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from "./ui/dropdown-menu";
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)42import type { Loaded } from "../lib/mission-control.server";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look43
44/*
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms45 * Mission control: the home page of someone signed in. It answers where
46 * the viewer is needed, what agents are doing, and what landed without
47 * them. It is a chunk of its own, loaded only for them, so the signed-out
48 * home page does not carry it. routes/home.tsx loads its data;
49 * lib/mission-control.ts shapes it.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look50 */
51
52/** The viewer's time zone, set by the page itself, so the greeting fits their day. */
53const TZ_COOKIE = "g1t_tz";
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms54/** Rows a tab shows before "See all". */
55const ROWS = 6;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look56
Money is written one way. A single formatter turns millionths of a dollar into dollars, rounding half up on whole micros rather than on a float, so the same sum reads the same on every page: under a cent reads <$0.01 on a total and exactly nothing is $0.00, while the statement's lines, a session's receipt, the price book and an agent's effort costs carry up to four places where the fraction of a cent is the point; the six formatters that each rounded their own way are gone. This month is the calendar month in UTC from its first day to today everywhere, and billing counts the month's not-yet-closed usage in any range that reaches into the current month, so the top bar's pill, Spend, Home and Usage ask for the same days and get the same figure; Home now reads the usage report the others read instead of adding up statements. Usage's pending sentence says what of that usage the close will charge after the discount and included usage, which the billing API returns as pending_charged_micros. A reconciliation test holds the pill, Spend, Home and Usage to one number for one month. The usage and billing guide says how amounts are written and what this month means.57const dollars = (micros: number) => money(Math.max(0, micros));
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms58const plural = (n: number, one: string, many = `${one}s`) => `${n.toLocaleString("en-US")} ${n === 1 ? one : many}`;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look59
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms60// --- Small pieces -----------------------------------------------------------------
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look61
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms62const CHIP_TONE: Record<Reason, string> = {
63 blocking: "border-danger/35 bg-danger/10 text-danger",
64 checks_failing: "border-danger/35 bg-danger/10 text-danger",
65 outside_guardrails: "border-warn/35 bg-warn/10 text-warn",
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step66 low_confidence: "border-warn/35 bg-warn/10 text-warn",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms67 stalled: "border-warn/35 bg-warn/10 text-warn",
Merge branch 'worktree-agent-ad7c6d88d93adc817'68 asked_for_you: "border-accent/35 bg-accent/10 text-accent",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms69 needs_review: "border-info/35 bg-info/10 text-info",
Merge branch 'worktree-agent-ad7c6d88d93adc817'70 ready_to_merge: "border-success/35 bg-success/10 text-success",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms71};
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look72
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms73function Chip({ children, tone }: { children: ReactNode; tone: string }) {
74 return (
75 <span
76 className={cn(
77 "inline-flex shrink-0 items-center rounded border px-1.5 py-px font-mono text-[0.625rem] font-medium tracking-wider whitespace-nowrap uppercase",
78 tone,
79 )}
80 >
81 {children}
82 </span>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look83 );
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms84}
85
86/** A person or an agent, by name, wearing the mark that tells them apart. */
87function Person({ who, size = 16, className }: { who: Who; size?: number; className?: string }) {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look88 return (
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms89 <span className={cn("inline-flex min-w-0 items-center gap-1.5", className)}>
90 <Avatar name={who.name} size={size} />
91 <span className="truncate">{who.name}</span>
92 </span>
93 );
94}
95
96function Eyebrow({ children }: { children: ReactNode }) {
97 return <p className="font-mono text-[0.625rem] font-medium tracking-[0.12em] text-faint uppercase">{children}</p>;
98}
99
Merge branch 'worktree-agent-ad7c6d88d93adc817'100const FACT_TONE = { good: "text-success", warn: "text-warn", bad: "text-danger" } as const;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms101
102function Facts({ facts }: { facts: Fact[] }) {
103 if (facts.length === 0) return <p className="text-sm text-muted">Nothing more is known about it yet.</p>;
104 return (
105 <dl className="grid grid-cols-2 gap-x-4 gap-y-2.5">
106 {facts.map((fact) => (
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step107 <div key={fact.label} className={cn("min-w-0", fact.wide && "col-span-2")}>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms108 <dt className="text-xs text-faint">{fact.label}</dt>
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step109 <dd
110 className={cn(
111 "mt-0.5 text-sm font-medium tabular-nums",
112 fact.wide ? "leading-5" : "truncate",
113 fact.tone ? FACT_TONE[fact.tone] : "text-fg-soft",
114 )}
115 >
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms116 {fact.value}
117 </dd>
118 </div>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look119 ))}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms120 </dl>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look121 );
122}
123
Merge branch 'worktree-agent-a985c01f43538af01'124/**
125 * A form that acts on a pull request from here: working until the action
126 * has answered and the page has reloaded what it changed, then done, or
127 * the error beside it.
128 */
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.129function QuickForm({ quick, variant = "outline" }: { quick: QuickAction; variant?: "outline" | "accent" }) {
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms130 const fetcher = useFetcher<{ error?: string } | null>();
131 const [sent, setSent] = useState(false);
Merge branch 'worktree-agent-a985c01f43538af01'132 const done = sent && fetcher.state === "idle" && !fetcher.data?.error;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look133 return (
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms134 <fetcher.Form method="post" action={quick.to} onSubmit={() => setSent(true)} className="contents">
135 {Object.entries(quick.fields).map(([name, value]) => (
136 <input key={name} type="hidden" name={name} value={value} />
137 ))}
Merge branch 'worktree-agent-a985c01f43538af01'138 <SubmitButton
139 fetcher={fetcher}
140 disabled={done}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms141 className={cn(
142 "inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors disabled:cursor-default",
143 variant === "accent"
Merge branch 'worktree-agent-ad7c6d88d93adc817'144 ? "bg-accent text-bg hover:bg-accent-hover"
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms145 : "border border-line-strong text-fg/90 hover:bg-raised hover:text-fg",
Merge branch 'worktree-agent-ad7c6d88d93adc817'146 done && "border-success/40 text-success",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms147 )}
148 >
Fast pages, required checks on the branch, self-hosted runners, honest incidents149 {done ? <Check size={14} /> : null}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms150 {done ? quick.done : quick.label}
Merge branch 'worktree-agent-a985c01f43538af01'151 </SubmitButton>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms152 {fetcher.data?.error && <span className="basis-full text-xs text-danger">{fetcher.data.error}</span>}
153 </fetcher.Form>
154 );
155}
156
157function ProjectMark({ repo }: { repo: { namespace: string; name: string } | null }) {
158 return <Avatar name={repo ? repo.name : "g1t"} size={32} square />;
159}
160
161/** A row that opens to what is known about it; the first one starts open. */
162function Row({
163 open,
164 repo,
165 by,
166 title,
167 sub,
168 chip,
169 at,
170 children,
171}: {
172 open: boolean;
173 repo: { namespace: string; name: string } | null;
174 by: Who | null;
175 title: ReactNode;
176 sub: ReactNode;
177 chip: ReactNode;
178 at: number;
179 children: ReactNode;
180}) {
181 return (
182 <li>
183 <details open={open} className="group">
184 <summary className="flex cursor-pointer list-none items-center gap-3 px-4 py-3 transition-colors select-none hover:bg-raised/60 sm:px-5 [&::-webkit-details-marker]:hidden">
185 <ProjectMark repo={repo} />
186 <span className="min-w-0 grow">
187 <span className="block truncate text-sm">{title}</span>
188 <span className="mt-0.5 flex min-w-0 items-center gap-1.5 text-xs text-muted">
189 <span className="shrink-0 font-medium text-fg-soft">{repo ? repo.name : "Workspace"}</span>
190 {by && (
191 <>
192 <span className="text-faint">·</span>
Merge branch 'worktree-agent-ad7c6d88d93adc817'193 <Person who={by} size={14} className={cn("shrink-0", by.agent ? "text-accent" : "")} />
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms194 </>
195 )}
196 {sub && (
197 <>
198 <span className="text-faint">—</span>
199 <span className="truncate">{sub}</span>
200 </>
201 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look202 </span>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms203 </span>
204 <span className="hidden sm:inline-flex">{chip}</span>
205 <span className="hidden w-16 shrink-0 text-right text-xs text-faint sm:block">
206 <TimeAgo at={at} />
207 </span>
208 <ChevronDown size={16} className="shrink-0 text-faint transition-transform group-open:rotate-180" />
209 </summary>
210 <div className="px-4 pb-4 sm:px-5 sm:pb-5">
211 <div className="mb-3 flex items-center gap-2 sm:hidden">
212 {chip}
213 <span className="text-xs text-faint">
214 <TimeAgo at={at} />
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look215 </span>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms216 </div>
217 {children}
218 </div>
219 </details>
220 </li>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look221 );
222}
223
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms224function NeedCard({ row, first }: { row: NeedRow; first: boolean }) {
225 const isPull = row.to.includes("/pull/");
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look226 return (
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms227 <Row
228 open={first}
229 repo={row.repo}
230 by={row.by}
231 title={
232 <>
233 <span className="font-medium">{row.title}</span>
234 {row.ref && <span className="ml-1 font-mono text-xs text-faint">{row.ref}</span>}
235 </>
236 }
237 sub={row.ask}
238 chip={<Chip tone={CHIP_TONE[row.reason]}>{REASON_LABEL[row.reason]}</Chip>}
239 at={row.at}
240 >
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.241 <Card tone="plain" className="grid gap-4 bg-bg/50 p-4 md:grid-cols-2 md:gap-x-6 2xl:grid-cols-[minmax(0,1.1fr)_minmax(0,1fr)_minmax(0,0.95fr)]">
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms242 <div className="min-w-0">
243 <Eyebrow>The ask</Eyebrow>
244 <p className="mt-2 text-sm leading-6 text-fg-soft">{row.ask}</p>
245 <p className="mt-2 text-xs leading-5 text-muted">
246 <Link to={row.to} className="font-medium text-fg hover:underline">
247 {row.repo ? `${row.repo.name}${row.ref ?? ""}` : row.title}
248 </Link>
249 {row.for && (
250 <>
251 {" "}
252 · started for <span className="text-fg-soft">{row.for}</span>
253 </>
254 )}
255 </p>
256 </div>
257 <div className="min-w-0">
Usage, Billing settings and prepaid AI credit; fixes from the UX audit258 <Eyebrow>{row.by?.agent ? "What the agent already knows" : "What is known"}</Eyebrow>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms259 <div className="mt-2">
260 <Facts facts={row.facts} />
261 </div>
262 </div>
263 <div className="rounded-lg border border-warn/20 bg-warn/[0.06] p-3.5 md:col-span-2 2xl:col-span-1">
264 <p className="text-xs font-semibold text-warn">Why this needs you</p>
265 <p className="mt-1.5 text-sm leading-6 text-fg-soft">{row.why}</p>
266 <p className="mt-2 text-xs text-faint">
Usage, Billing settings and prepaid AI credit; fixes from the UX audit267 Started waiting <TimeAgo at={row.at} />
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms268 </p>
269 </div>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.270 </Card>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms271 <div className="mt-3 flex flex-wrap items-center gap-2">
272 <Link
273 to={row.to}
274 prefetch="intent"
You choose how g1t looks: Auto follows your system, Light and Dark stay put, set from the account menu, the phone's You and help sheet, Settings → Account or the command palette; the page is drawn in your choice from the first byte, every colour has a light value that reads at 4.5:1 or better, code and diffs are highlighted for both, diagrams and the document editor follow along, the product tour and the g1t mark's avatar stay dark, and Dark is what you see until you choose; the workspaces guide says how.275 className="inline-flex items-center gap-1.5 rounded-md bg-fg px-3 py-1.5 text-sm font-medium text-bg transition-colors hover:bg-fg-hover"
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms276 >
277 Review and respond <ArrowUpRight size={14} />
278 </Link>
279 {row.quick && <QuickForm quick={row.quick} />}
280 {row.link && (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look281 <Link
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms282 to={row.link.to}
283 className="inline-flex items-center rounded-md border border-line-strong px-3 py-1.5 text-sm font-medium text-fg/90 hover:bg-raised hover:text-fg"
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look284 >
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms285 {row.link.label}
286 </Link>
287 )}
288 {row.open !== row.to && (
289 <Link to={row.open} prefetch="intent" className="px-2 py-1.5 text-sm text-muted hover:text-fg">
290 {row.open.includes("/issues/") ? "Open issue" : isPull ? "See the changes" : "Open pull request"}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look291 </Link>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms292 )}
293 </div>
294 </Row>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look295 );
296}
297
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms298function WaitingCard({ row, first }: { row: WaitingRow; first: boolean }) {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look299 return (
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms300 <Row
301 open={first}
302 repo={row.repo}
303 by={row.by}
304 title={
305 <>
306 <span className="font-medium">{row.title}</span>
307 {row.ref && <span className="ml-1 font-mono text-xs text-faint">{row.ref}</span>}
308 </>
309 }
310 sub={row.detail}
311 chip={
312 <Chip tone="border-line-strong bg-raised text-muted">
Merge branch 'worktree-agent-ad7c6d88d93adc817'313 {row.live && <span className="mr-1.5 size-1.5 animate-pulse rounded-full bg-success" />}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms314 {row.chip}
315 </Chip>
316 }
317 at={row.at}
318 >
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.319 <Card tone="plain" className="grid gap-4 bg-bg/50 p-4 md:grid-cols-2 md:gap-6">
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms320 <div className="min-w-0">
321 <Eyebrow>{row.live ? "Doing now" : "Where it stands"}</Eyebrow>
322 <p className="mt-2 text-sm leading-6 text-fg-soft">{row.detail}</p>
323 </div>
324 <div className="min-w-0">
325 <Eyebrow>What is known</Eyebrow>
326 <div className="mt-2">
327 <Facts facts={row.facts} />
328 </div>
329 </div>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.330 </Card>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms331 <div className="mt-3 flex flex-wrap gap-2">
332 <Link
333 to={row.to}
334 prefetch="intent"
335 className="inline-flex items-center gap-1.5 rounded-md border border-line-strong px-3 py-1.5 text-sm font-medium text-fg/90 hover:bg-raised hover:text-fg"
336 >
337 {row.to.includes("/runs/") ? "Watch the run" : "Open pull request"} <ArrowUpRight size={14} />
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look338 </Link>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms339 {row.run && row.run !== row.to && (
340 <Link to={row.run} prefetch="intent" className="px-2 py-1.5 text-sm text-muted hover:text-fg">
341 Watch the run
342 </Link>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look343 )}
344 </div>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms345 </Row>
346 );
347}
348
349function LandedCard({ row, first }: { row: LandedRow; first: boolean }) {
350 return (
351 <Row
352 open={first}
353 repo={row.repo}
354 by={row.byAgents ? { name: row.agent, agent: isAgent(row.agent) } : row.by}
355 title={
356 <>
357 <span className="font-medium">{row.title}</span>
358 <span className="ml-1 font-mono text-xs text-faint">{row.ref}</span>
359 </>
360 }
361 sub={row.byAgents ? "landed without a person" : `merged by ${row.by?.name ?? "a person"}`}
362 chip={
363 row.byAgents ? (
Merge branch 'worktree-agent-ad7c6d88d93adc817'364 <Chip tone="border-accent/35 bg-accent/10 text-accent">By agents</Chip>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look365 ) : (
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms366 <Chip tone="border-warn/35 bg-warn/10 text-warn">Needed a person</Chip>
367 )
368 }
369 at={row.at}
370 >
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.371 <Card tone="plain" className="grid gap-4 bg-bg/50 p-4 md:grid-cols-2 md:gap-6">
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms372 <div className="min-w-0">
373 <Eyebrow>How it landed</Eyebrow>
374 <p className="mt-2 text-sm leading-6 text-fg-soft">
375 {row.byAgents
376 ? `g1t merged it once everything the repository asks for was met, with no one pressing merge.`
377 : `${row.by?.name ?? "A person"} merged it.`}
378 {row.agent && isAgent(row.agent) && ` ${row.agent} made the change.`}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look379 </p>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms380 </div>
381 <div className="min-w-0">
382 <Eyebrow>What changed</Eyebrow>
383 <div className="mt-2">
384 <Facts facts={row.facts} />
385 </div>
386 </div>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.387 </Card>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms388 <div className="mt-3">
389 <Link
390 to={row.to}
391 prefetch="intent"
392 className="inline-flex items-center gap-1.5 rounded-md border border-line-strong px-3 py-1.5 text-sm font-medium text-fg/90 hover:bg-raised hover:text-fg"
393 >
394 Open pull request <ArrowUpRight size={14} />
395 </Link>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look396 </div>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms397 </Row>
398 );
399}
400
401function List({ children }: { children: ReactNode }) {
402 return <ul className="divide-y divide-line">{children}</ul>;
403}
404
405function Empty({ children, action }: { children: ReactNode; action?: ReactNode }) {
406 return (
407 <div className="px-5 py-10 text-center">
408 <div className="mx-auto max-w-md text-sm leading-6 text-muted">{children}</div>
409 {action && <div className="mt-4 flex flex-wrap justify-center gap-2">{action}</div>}
410 </div>
411 );
412}
413
414// --- The stat strip -----------------------------------------------------------------
415
416function Stat({ label, value, hint, dot, title }: { label: string; value: string; hint: ReactNode; dot?: string; title?: string }) {
417 return (
Merge branch 'worktree-agent-ae1299e92e4462012'418 <Hint label={title}>
419 <div className="min-w-0 bg-surface px-4 py-3.5 sm:px-5 sm:py-4">
420 <p className="flex items-center gap-1.5 truncate text-xs text-muted">
421 {dot && <span className={cn("size-1.5 shrink-0 rounded-full", dot)} />}
422 {label}
423 </p>
424 <p className="mt-1 font-display text-2xl font-semibold tracking-tight tabular-nums sm:text-[1.75rem]">{value}</p>
425 <p className="mt-0.5 truncate text-xs text-faint">{hint}</p>
426 </div>
427 </Hint>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms428 );
429}
430
431// --- This week ----------------------------------------------------------------------
432
433/** Seven days of landed changes, each split into what agents landed alone and what a person merged. */
434function WeekChart({ week }: { week: Week }) {
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar435 const max = Math.max(1, ...week.days.map((d) => d.agents + d.assisted + d.people));
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms436 const height = 112;
437 const delta = change(week.total, week.previous);
438 return (
439 <div>
440 <div className="flex items-end justify-between gap-3">
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look441 <div>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms442 <p className="font-display text-3xl font-semibold tracking-tight tabular-nums">{week.total.toLocaleString("en-US")}</p>
443 <p className="text-xs text-muted">changes landed in 7 days</p>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look444 </div>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms445 {delta != null ? (
446 <span
447 className={cn(
448 "rounded-full px-2 py-0.5 text-xs font-medium tabular-nums ring-1",
Merge branch 'worktree-agent-ad7c6d88d93adc817'449 delta >= 0 ? "text-success ring-success/30" : "text-warn ring-warn/30",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms450 )}
451 >
452 {signedPercent(delta)} vs last week
453 </span>
454 ) : week.previous === 0 && week.total > 0 ? (
455 <span className="text-xs text-faint">none the week before</span>
456 ) : null}
457 </div>
458 {week.total === 0 ? (
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.459 <Card asChild tone="plain" radius="lg" className="mt-4 border-dashed px-4 py-6 text-center text-sm leading-6 text-muted">
460 <p>
461 Nothing landed in the last 7 days. Each change that does shows here, by day: agents' changes that landed on their own, agents' that a person merged, and people's own.
462 </p>
463 </Card>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms464 ) : (
465 <div className="relative mt-5" style={{ height: height + 20 }}>
466 <div className="absolute inset-x-0 border-t border-line" style={{ top: height }} />
467 <div className="absolute inset-x-0 top-0 flex items-end justify-between gap-1" style={{ height }}>
468 {week.days.map((day, index) => {
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar469 const total = day.agents + day.assisted + day.people;
470 const bar = (n: number) => Math.max(3, Math.round((n / max) * (height - 4)));
471 // Top to bottom: agents alone, agents with a person, people.
472 const segments = [
Merge branch 'worktree-agent-ad7c6d88d93adc817'473 { n: day.agents, tone: "bg-accent" },
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar474 { n: day.assisted, tone: "bg-warn" },
475 { n: day.people, tone: "bg-info" },
476 ].filter((segment) => segment.n > 0);
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms477 const today = index === week.days.length - 1;
478 return (
479 <div key={day.key} className="group relative flex h-full flex-1 flex-col items-center justify-end">
480 {total > 0 && (
481 <span
482 className={cn(
483 "mb-1 text-[0.625rem] tabular-nums",
Phones reach every page: each mode's menu from the top bar or by tapping the tab you're on, Docs first in the avatar sheet, a project's pages as a swipeable strip; dialogs as bottom sheets above the keyboard, safe areas, menus kept on screen, 40px targets, touch-visible controls, save bars above the tab bar484 today ? "text-fg-soft" : "text-faint opacity-0 group-hover:opacity-100 max-md:hidden",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms485 )}
486 >
487 {total}
488 </span>
489 )}
490 <div className="flex w-full max-w-6 flex-col items-stretch gap-[2px]">
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar491 {segments.map((segment, at) => (
492 <span key={segment.tone} className={cn("block", segment.tone, at === 0 && "rounded-t")} style={{ height: bar(segment.n) }} />
493 ))}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms494 {total === 0 && <span className="block h-[2px] rounded-full bg-line-strong" />}
495 </div>
Phones reach every page: each mode's menu from the top bar or by tapping the tab you're on, Docs first in the avatar sheet, a project's pages as a swipeable strip; dialogs as bottom sheets above the keyboard, safe areas, menus kept on screen, 40px targets, touch-visible controls, save bars above the tab bar496 <div className="pointer-events-none absolute bottom-full left-1/2 z-10 mb-1 hidden -translate-x-1/2 rounded-md border border-line-strong bg-raised px-2.5 py-1.5 text-xs whitespace-nowrap shadow-lg shadow-black/40 md:group-hover:block">
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms497 <p className="font-medium text-fg">{day.label}</p>
498 <p className="mt-0.5 flex items-center gap-1.5 text-muted">
Merge branch 'worktree-agent-ad7c6d88d93adc817'499 <span className="size-1.5 rounded-full bg-accent" /> {day.agents} by agents on their own
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar500 </p>
501 <p className="flex items-center gap-1.5 text-muted">
502 <span className="size-1.5 rounded-full bg-warn" /> {day.assisted} by agents, merged by a person
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms503 </p>
504 <p className="flex items-center gap-1.5 text-muted">
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar505 <span className="size-1.5 rounded-full bg-info" /> {day.people} by people
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms506 </p>
507 </div>
508 </div>
509 );
510 })}
511 </div>
512 <div className="absolute inset-x-0 bottom-0 flex justify-between gap-1">
513 {week.days.map((day, index) => (
514 <span
515 key={day.key}
516 className={cn(
517 "flex-1 text-center text-[0.6875rem]",
518 index === week.days.length - 1 ? "font-medium text-fg-soft" : "text-faint",
519 )}
520 >
521 {day.label}
522 </span>
523 ))}
524 </div>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look525 </div>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms526 )}
527 <div className={cn("mt-3 flex-wrap gap-x-4 gap-y-1 text-xs text-muted", week.total === 0 ? "hidden" : "flex")}>
528 <span className="inline-flex items-center gap-1.5">
Merge branch 'worktree-agent-ad7c6d88d93adc817'529 <span className="size-2 rounded-sm bg-accent" /> Agents, on their own
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar530 </span>
531 <span className="inline-flex items-center gap-1.5">
532 <span className="size-2 rounded-sm bg-warn" /> Agents, merged by a person
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms533 </span>
534 <span className="inline-flex items-center gap-1.5">
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar535 <span className="size-2 rounded-sm bg-info" /> People
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms536 </span>
537 </div>
Fixes from the page sweep538 {/* A table does not shrink to sr-only's 1px; its wrapper does. */}
539 <div className="sr-only">
540 <table>
541 <caption>Changes landed each day</caption>
542 <thead>
543 <tr>
544 <th>Day</th>
545 <th>Agents, on their own</th>
546 <th>Agents, merged by a person</th>
547 <th>People</th>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms548 </tr>
Fixes from the page sweep549 </thead>
550 <tbody>
551 {week.days.map((day) => (
552 <tr key={day.key}>
553 <td>{day.key}</td>
554 <td>{day.agents}</td>
555 <td>{day.assisted}</td>
556 <td>{day.people}</td>
557 </tr>
558 ))}
559 </tbody>
560 </table>
561 </div>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms562 </div>
563 );
564}
565
566// --- Activity -----------------------------------------------------------------------
567
568const VERB: Record<Verb, string> = {
569 landed: "landed",
570 opened_issue: "opened",
571 closed_issue: "closed",
572 started: "started on",
573 ready: "marked ready",
574 checks_passed: "checks passed on",
575 checks_failed: "checks failed on",
576 approved: "approved",
577 changes_requested: "asked for changes on",
578 commented: "commented on",
579 asked: "was asked about",
580 deployed: "deployed production",
581 deploy_failed: "production build failed",
Merge demo dry run fixes: settled checks, other attempts, queue links, clone box, activity feed, DEMO.md582 pushed: "pushed to the default branch",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms583 learned: "learned",
584};
585
586/** One line of the feed: who, what, and the one thing it was about, by name. */
587function FeedLine({ group, titles }: { group: ActivityGroup; titles: Record<string, string> }) {
588 const part = group.parts[0];
589 const base = `/${group.repo.namespace}/${group.repo.name}`;
590 const actor = group.actor ?? "g1t";
591 const agent = group.actor == null || isAgent(group.actor);
592 const number = part.numbers[0];
593 const title = number != null ? titles[`${group.repo.namespace}/${group.repo.name}#${number}`.toLowerCase()] : undefined;
594 const more = group.parts.length - 1 + Math.max(0, part.numbers.length - 1);
595 return (
596 <li className="flex gap-2.5 py-2">
597 <span className="mt-px">
598 <Avatar name={actor} size={22} />
599 </span>
600 <span className="min-w-0 grow text-[0.8125rem] leading-5 text-muted">
Merge branch 'worktree-agent-ad7c6d88d93adc817'601 <span className={cn("font-medium", agent ? "text-accent" : "text-fg")}>{actor}</span> {VERB[part.verb]}{" "}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms602 {part.verb === "learned" ? (
603 <Link to={part.to ?? `${base}/memory`} className="text-fg-soft hover:text-fg">
604 “{part.texts[0]}”
605 </Link>
606 ) : number != null ? (
607 <Link to={`${base}/issues/${number}`} prefetch="intent" className="text-fg-soft hover:text-fg">
608 <span className="font-mono text-xs">#{number}</span>
609 {title && <> {title}</>}
610 </Link>
611 ) : part.to ? (
612 <Link to={part.to} className="text-fg-soft hover:text-fg">
613 {group.repo.name}
614 </Link>
615 ) : null}
616 {more > 0 && <span className="text-faint"> and {more} more</span>}
617 <span className="block text-xs text-faint">
618 <span className="font-mono">{group.repo.name}</span> · <TimeAgo at={group.at} />
619 </span>
620 </span>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look621 </li>
622 );
623}
624
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms625// --- Get started --------------------------------------------------------------------
626
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look627type Step = { done: boolean; title: string; about: string; to: string | null; action: string };
628
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms629/** The first things to do, ticked off as they are done, until work has been handed to agents. */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look630function GetStarted({ steps }: { steps: Step[] }) {
631 const left = steps.filter((step) => !step.done).length;
632 return (
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.633 <Card asChild className="p-5">
634 <section>
635 <div className="flex items-baseline justify-between gap-3">
636 <h2 className="text-base font-semibold tracking-tight">Get started</h2>
637 <span className="text-xs text-muted">
638 {steps.length - left} of {steps.length} done
639 </span>
640 </div>
641 <ol className="mt-4 space-y-2">
642 {steps.map((step, index) => (
643 <li
644 key={step.title}
645 className={cn("flex items-start gap-3 rounded-lg px-3 py-2.5", step.done ? "" : "bg-bg/50 ring-1 ring-line")}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look646 >
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.647 <span
648 className={cn(
649 "mt-0.5 flex size-5 shrink-0 items-center justify-center rounded-full text-[0.6875rem] font-medium",
650 step.done ? "bg-success text-bg" : "text-muted ring-1 ring-line-strong",
651 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look652 >
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.653 {step.done ? <Check size={12} /> : index + 1}
654 </span>
655 <span className="min-w-0 grow">
656 <span className={cn("block text-sm font-medium", step.done && "text-muted line-through decoration-faint")}>{step.title}</span>
657 {!step.done && <span className="mt-0.5 block text-xs leading-5 text-muted">{step.about}</span>}
658 </span>
659 {!step.done && step.to && (
660 <Link
661 to={step.to}
662 className="shrink-0 rounded-md bg-fg px-2.5 py-1 text-xs font-medium text-bg transition-colors hover:bg-fg-hover"
663 >
664 {step.action}
665 </Link>
666 )}
667 </li>
668 ))}
669 </ol>
670 </section>
671 </Card>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look672 );
673}
674
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms675// --- The page -----------------------------------------------------------------------
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look676
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms677const TAB_LABEL: Record<Tab, string> = { needs: "Needs you", waiting: "Waiting on agents", landed: "Landed today" };
678const TAB_SHORT: Record<Tab, string> = { needs: "Needs you", waiting: "Waiting", landed: "Today" };
679const SORT_LABEL: Record<Sort, string> = { impact: "By impact", newest: "Newest" };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look680
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)681export default function MissionControl({
682 loaderData,
683 delegated = null,
684 variant = "code",
685}: {
686 loaderData: Loaded;
687 delegated?: ComposerResult;
688 /** Code's Overview: its own title in place of the greeting, and the actions on their own (Home has the Agent box). */
689 variant?: "code";
690}) {
691 const { pathname } = useLocation();
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look692 const shell = useRouteLoaderData("root")?.shell as ShellData | null | undefined;
693 const loaded: Loaded = loaderData;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms694 const [params] = useSearchParams();
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look695 // Agents are at work, so the page changes without anyone touching it.
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms696 useLiveRefresh(loaded.changing);
697 const [greeting, setGreeting] = useState(loaded.greeting);
698 const [date, setDate] = useState(loaded.date);
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look699 useEffect(() => {
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms700 // The greeting and date follow the viewer's own clock, and the server
701 // learns their zone for next time.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look702 setGreeting(greetingFor(new Date().getHours()));
703 try {
704 const zone = Intl.DateTimeFormat().resolvedOptions().timeZone;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms705 setDate(dateLine(Date.now(), zone ?? null));
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look706 if (zone) document.cookie = `${TZ_COOKIE}=${encodeURIComponent(zone)}; Path=/; Max-Age=31536000; SameSite=Lax`;
707 } catch {
708 // Nothing to remember.
709 }
710 }, []);
711
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms712 const { viewer, repos, waiting, landed, liveTotal, week, groups, titles, stats, canRunAgents, trial } = loaded;
713 const workspace = shell?.workspace?.slug ?? loaded.workspace ?? viewer.workspaces?.[0]?.slug ?? null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look714
715 // The usage limit, as the sidebar knows it, heads the list when it bites.
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms716 const limit = shell?.limit && !shell.limit.comped && shell.limit.state !== "ok" && workspace ? shell.limit : null;
717 const limitRow: NeedRow[] = limit
718 ? [
719 (() => {
720 const detail =
721 limit.state === "stopped"
722 ? "No new agent starts until the limit is raised or a card is added."
723 : `${dollars(limit.exposureMicros)} of ${dollars(limit.ceilingMicros ?? 0)} used. Add a card so work keeps going.`;
724 return {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look725 key: "limit",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms726 reason: "blocking" as const,
727 repo: null,
728 ref: null,
729 title: limit.state === "stopped" ? "Agents are stopped: the usage limit was reached" : "Usage is nearing its limit",
730 ask: detail,
731 by: null,
732 for: null,
733 at: Date.now(),
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look734 to: `/${workspace}/-/billing`,
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms735 open: `/${workspace}/-/billing`,
736 facts: [
737 { label: "Used", value: `${dollars(limit.exposureMicros)} of ${dollars(limit.ceilingMicros ?? 0)}`, tone: "warn" as const },
738 ],
739 why: whyFor("blocking", { kind: "limit", detail }),
740 quick: null,
741 link: null,
742 };
743 })(),
744 ]
745 : [];
746 const needs = [...limitRow, ...loaded.needs];
747 const blocking = needs.filter((row) => BLOCKING.has(row.reason)).length;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look748
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms749 const counts: Record<Tab, number> = { needs: needs.length, waiting: waiting.length, landed: landed.length };
750 const tab = parseTab(params.get("tab")) ?? "needs";
751 const sort = parseSort(params.get("sort"));
752 const all = params.get("all") === "1";
753 const everyActivity = params.get("activity") === "all";
754 const link = (changes: Record<string, string | null>) => {
755 const next = new URLSearchParams(params);
756 for (const [key, value] of Object.entries(changes)) {
757 if (value == null) next.delete(key);
758 else next.set(key, value);
759 }
760 const text = next.toString();
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)761 return text ? `?${text}` : pathname;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms762 };
763
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look764 const steps: Step[] = [
765 {
766 done: Boolean(workspace),
767 title: "Create a workspace",
768 about: "Projects, people and agent credit live in one.",
769 to: "/workspaces/new",
770 action: "Create",
771 },
772 {
773 done: repos.length > 0,
774 title: "Add a project",
775 about: "Create a repository, or import one by its address. Push to it with git as usual.",
New project and Import from GitHub work in the workspace you're in, as the sidebar shows it, with no workspace to pick on the page; a link that names another of your workspaces switches you to it first. The projects guide says so.776 to: "/new",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look777 action: "Add",
778 },
779 trial?.open
780 ? {
781 done: true,
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent782 title: "Try g1t free",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look783 about: trial.granted
784 ? `This workspace has ${dollars(trial.limitMicros - trial.usedMicros)} of its ${dollars(trial.limitMicros)} trial credit left, for g1t's models and sandboxes.`
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent785 : `This workspace gets ${dollars(trial.limitMicros)} of trial credit, for g1t's models and sandboxes, the first time g1t works here.`,
Integrations are a directory of connectors, for a workspace and for each person786 to: workspace ? `/${workspace}/-/integrations/models` : null,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look787 action: "Connect",
788 }
789 : canRunAgents
790 ? {
791 done: Boolean(shell?.free) || shell?.limit == null || shell.limit.comped || shell.limit.state === "ok",
792 title: "Keep work running",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms793 about:
794 "Usage is charged after it runs. Add a card under Billing, so g1t charges it as you near your limit instead of stopping work.",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look795 to: workspace ? `/${workspace}/-/billing` : null,
796 action: "Billing",
797 }
798 : {
799 done: false,
800 title: "Connect a model",
801 about: `${
802 trialClosed(trial, workspace ?? "This workspace") ? `${trialClosed(trial, workspace ?? "This workspace")} ` : ""
803 }Agents need a model to think with. Connect your Anthropic or OpenAI key, or any compatible endpoint.`,
Integrations are a directory of connectors, for a workspace and for each person804 to: workspace ? `/${workspace}/-/integrations/models` : null,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look805 action: "Connect",
806 },
807 {
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms808 done: loaded.handedOff,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look809 title: "Hand off an outcome",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms810 about:
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent811 "Open an issue and assign it to g1t, or write an outcome on a project's Plans page and let a planner split it into issues.",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms812 to: repos[0] ? `/${repos[0].namespace}/${repos[0].name}/plans` : null,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look813 action: "Write one",
814 },
815 ];
816 const starting = steps.some((step) => !step.done);
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms817 const noProjects = repos.length === 0;
818
819 const rows = tab === "needs" ? sortRows(needs, sort) : tab === "waiting" ? sortRows(waiting, sort) : sortRows(landed, sort);
820 const shown = all ? rows : rows.slice(0, ROWS);
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar821 // Of the agents' own changes only: people's work is not theirs to land.
822 const share = week.agentChanges > 0 ? week.byAgents / week.agentChanges : null;
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms823 const delta = change(week.total, week.previous);
824 const feed = everyActivity ? groups : groups.slice(0, 8);
825
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step826 // "Put an agent on it" first, with "New issue" beside it as before: one
827 // split control, the agent the main way in.
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms828 const newIssue =
829 repos.length > 0 ? (
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step830 <div className="flex items-stretch">
831 <AgentComposer
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)832 action={pathname}
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step833 repos={repos}
834 open={params.get("agent") === "new" || delegated != null}
835 result={delegated}
836 note={
837 canRunAgents ? null : (
838 <>
839 Agents need a model first.{" "}
840 {workspace && (
Integrations are a directory of connectors, for a workspace and for each person841 <Link to={`/${workspace}/-/integrations/models`} className="font-medium text-fg hover:underline">
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step842 Connect one
843 </Link>
844 )}
845 . The issue still opens.
846 </>
847 )
848 }
849 >
850 <span className="inline-flex cursor-pointer items-center gap-1.5 rounded-l-md border border-line-strong bg-raised px-3 py-2 text-sm font-medium text-fg transition-colors hover:bg-line/60 group-open/composer:bg-line/60">
Merge branch 'worktree-agent-ad7c6d88d93adc817'851 <Sparkles size={14} className="text-accent" /> Put an agent on it
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step852 </span>
853 </AgentComposer>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms854 <DropdownMenu>
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step855 <DropdownMenuTrigger className="-ml-px inline-flex items-center gap-1.5 rounded-r-md border border-line-strong px-3 py-2 text-sm font-medium text-fg/90 transition-colors hover:bg-raised hover:text-fg">
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms856 <Plus size={14} /> New issue
857 </DropdownMenuTrigger>
858 <DropdownMenuContent align="end" className="max-h-80 overflow-y-auto">
859 <DropdownMenuLabel>In which project?</DropdownMenuLabel>
860 {repos.map((repo) => (
861 <DropdownMenuItem key={repo.name} asChild>
862 <Link to={`/${repo.namespace}/${repo.name}/issues/new`}>
863 <Avatar name={repo.name} size={18} square />
864 {repo.name}
865 </Link>
866 </DropdownMenuItem>
867 ))}
868 </DropdownMenuContent>
869 </DropdownMenu>
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step870 </div>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms871 ) : (
872 <Link
New project and Import from GitHub work in the workspace you're in, as the sidebar shows it, with no workspace to pick on the page; a link that names another of your workspaces switches you to it first. The projects guide says so.873 to={"/new"}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms874 className="inline-flex items-center gap-1.5 rounded-md border border-line-strong px-3 py-2 text-sm font-medium text-fg/90 hover:bg-raised hover:text-fg"
875 >
876 <Plus size={14} /> New project
877 </Link>
878 );
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look879
880 return (
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms881 <main className="mx-auto max-w-7xl space-y-6 px-4 py-8 sm:px-6 sm:py-10">
882 <header className="flex flex-wrap items-end justify-between gap-x-6 gap-y-4">
883 <div className="min-w-0">
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)884 <h1 className="text-2xl leading-tight font-semibold tracking-tight" suppressHydrationWarning>
885 {variant === "code" ? "Overview" : `${greeting}, ${loaded.name}`}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look886 </h1>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms887 <p className="mt-1.5 text-sm text-muted" suppressHydrationWarning>
888 <span className="text-fg-soft">{date}</span> · {loaded.summary}
889 </p>
890 </div>
891 </header>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look892
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)893 {/* The ways to start work. The Agent box itself is on Home. */}
894 <section aria-label="Start work" className="flex flex-wrap items-center gap-2">
Mission control: a place to ask g1t, shown and not on yet, with the actions under it895 {newIssue}
896 {repos.length > 0 && (
897 <DropdownMenu>
898 <DropdownMenuTrigger className="inline-flex items-center gap-1.5 rounded-md border border-line-strong px-3 py-2 text-sm font-medium text-fg/90 transition-colors hover:bg-raised hover:text-fg">
899 <ListTree size={14} /> Plan work
900 </DropdownMenuTrigger>
901 <DropdownMenuContent align="start" className="max-h-80 overflow-y-auto">
902 <DropdownMenuLabel>Plan in which project?</DropdownMenuLabel>
903 {repos.map((repo) => (
904 <DropdownMenuItem key={repo.name} asChild>
905 <Link to={`/${repo.namespace}/${repo.name}/plans`}>
906 <Avatar name={repo.name} size={18} square />
907 {repo.name}
908 </Link>
909 </DropdownMenuItem>
910 ))}
911 </DropdownMenuContent>
912 </DropdownMenu>
913 )}
914 {needs.length > 0 && (
915 <Link
916 to={`${link({ tab: "needs", all: null })}#work`}
917 preventScrollReset
Merge branch 'worktree-agent-ad7c6d88d93adc817'918 className="inline-flex items-center gap-1.5 rounded-md bg-accent px-3.5 py-2 text-sm font-semibold text-bg transition-colors hover:bg-accent-hover"
Mission control: a place to ask g1t, shown and not on yet, with the actions under it919 >
920 Review {needs.length} that need{needs.length === 1 ? "s" : ""} you <ArrowRight size={14} />
921 </Link>
922 )}
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)923 </section>
Mission control: a place to ask g1t, shown and not on yet, with the actions under it924
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms925 {starting && <GetStarted steps={steps} />}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look926
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.927 <Card asChild tone="plain" className="grid grid-cols-2 gap-px overflow-hidden bg-line lg:grid-cols-5">
928 <section
929 aria-label="At a glance">
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms930 <Stat
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.931 label="Projects"
932 value={stats.projects == null ? "—" : String(stats.projects)}
933 hint={
934 stats.projectsThisMonth == null
935 ? "in this workspace"
936 : stats.projectsThisMonth > 0
937 ? `+${stats.projectsThisMonth} this month`
938 : "none new this month"
939 }
940 />
941 <Stat
942 label="Agents"
943 value={loaded.runsLoaded || !workspace ? String(liveTotal) : "—"}
944 dot={liveTotal > 0 ? "bg-success animate-pulse" : undefined}
945 hint={
946 liveTotal > 0
947 ? `live now · ${stats.agentHours < 10 ? stats.agentHours.toFixed(1) : Math.round(stats.agentHours)}h this week`
948 : stats.agentHours > 0
949 ? `none live · ${stats.agentHours < 10 ? stats.agentHours.toFixed(1) : Math.round(stats.agentHours)}h this week`
950 : "none live now"
951 }
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms952 />
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.953 <Stat
954 label="Changes this week"
955 value={loaded.perRepoLoaded ? String(week.total) : "—"}
956 hint={
957 delta != null ? `${signedPercent(delta)} vs last week` : week.previous === 0 ? "none the week before" : "merged pull requests"
958 }
959 />
960 <Stat
961 label="Landed without you"
962 dot="bg-accent"
963 value={share == null ? "—" : `${Math.round(share * 100)}%`}
964 hint={share == null ? "no agent changes yet" : `${week.byAgents} of ${week.agentChanges} agent changes`}
965 title="Of the changes agents wrote, those g1t merged by auto-merge or the merge queue, with no person pressing merge. People's own changes are not counted."
966 />
967 <div className="col-span-2 lg:col-span-1">
968 <Stat
969 label="Needs you"
970 dot="bg-warn"
971 value={String(needs.length)}
972 hint={blocking > 0 ? `${blocking} blocking` : needs.length > 0 ? "nothing blocking" : "all clear"}
973 />
974 </div>
975 </section>
976 </Card>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look977
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms978 <div className="grid gap-6 lg:grid-cols-[minmax(0,1fr)_21rem] xl:grid-cols-[minmax(0,1fr)_23rem]">
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.979 <Card asChild className="min-w-0 scroll-mt-20 self-start overflow-hidden">
980 <section id="work">
981 <div className="flex items-center gap-2 border-b border-line px-2 sm:px-3">
982 <nav className="-mb-px flex min-w-0 grow gap-1 overflow-x-auto [scrollbar-width:none]" aria-label="Overview">
983 {(["needs", "waiting", "landed"] as const).map((value) => (
984 <Link
985 key={value}
986 to={link({ tab: value, all: null })}
987 preventScrollReset
988 aria-current={tab === value ? "page" : undefined}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms989 className={cn(
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.990 "flex shrink-0 items-center gap-1.5 border-b-2 px-2 py-3 text-sm whitespace-nowrap transition-colors sm:px-2.5",
991 tab === value ? "border-accent font-medium text-fg" : "border-transparent text-muted hover:text-fg",
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms992 )}
993 >
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.994 <span className="sm:hidden">{TAB_SHORT[value]}</span>
995 <span className="hidden sm:inline">{TAB_LABEL[value]}</span>
996 <span
997 className={cn(
998 "rounded-full px-1.5 text-[0.6875rem] tabular-nums",
999 tab === value && value === "needs" && counts.needs > 0 ? "bg-warn/15 text-warn" : "bg-line text-muted",
1000 )}
1001 >
1002 {counts[value]}
1003 </span>
1004 </Link>
1005 ))}
1006 </nav>
1007 <DropdownMenu>
1008 <DropdownMenuTrigger
1009 className="inline-flex shrink-0 items-center gap-1.5 rounded-md px-2 py-1.5 text-xs text-muted hover:bg-raised hover:text-fg"
1010 aria-label="Sort"
1011 >
1012 <ArrowDownWideNarrow size={14} />
1013 <span className="hidden sm:inline">{SORT_LABEL[sort]}</span>
1014 </DropdownMenuTrigger>
1015 <DropdownMenuContent align="end">
1016 {(["impact", "newest"] as const).map((value) => (
1017 <DropdownMenuItem key={value} asChild>
1018 <Link to={link({ sort: value === "impact" ? null : value })} preventScrollReset>
1019 {sort === value ? <Check /> : <span className="size-4" />}
1020 {SORT_LABEL[value]}
1021 </Link>
1022 </DropdownMenuItem>
1023 ))}
1024 </DropdownMenuContent>
1025 </DropdownMenu>
1026 </div>
1027
1028 {!loaded.perRepoLoaded && tab !== "waiting" ? (
1029 <div className="p-4">
1030 <Unavailable what={tab === "needs" ? "Some of what needs you" : "What landed"} />
1031 </div>
1032 ) : null}
1033
1034 {tab === "needs" &&
1035 (needs.length === 0 ? (
1036 noProjects ? (
1037 <Empty
1038 action={
1039 <Link
1040 to={"/new"}
1041 className="rounded-md bg-fg px-3 py-1.5 text-sm font-medium text-bg hover:bg-fg-hover"
1042 >
1043 Create or import a project
1044 </Link>
1045 }
1046 >
1047 <p className="font-medium text-fg">No projects yet</p>
1048 <p className="mt-1">
1049 Create a repository or import one. Assign its issues to g1t, and what needs you shows up here.
1050 </p>
1051 </Empty>
1052 ) : (
1053 <>
1054 <Empty>
1055 <p className="font-medium text-fg">Nothing needs you</p>
1056 <p className="mt-1">
1057 Agents are handling everything.{" "}
1058 {landed.length > 0
1059 ? "Here's what they landed today."
1060 : "Reviews, stopped work and failed deploys show up here first."}
1061 </p>
1062 </Empty>
1063 {landed.length > 0 && (
1064 <div className="border-t border-line">
1065 <List>
1066 {landed.slice(0, ROWS).map((row) => (
1067 <LandedCard key={row.key} row={row} first={false} />
1068 ))}
1069 </List>
1070 </div>
1071 )}
1072 </>
1073 )
1074 ) : (
1075 <List>
1076 {(shown as NeedRow[]).map((row, index) => (
1077 <NeedCard key={row.key} row={row} first={index === 0} />
1078 ))}
1079 </List>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1080 ))}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1081
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1082 {tab === "waiting" &&
1083 (!loaded.runsLoaded && workspace ? (
1084 <div className="p-4">
1085 <Unavailable what="Agent runs" />
1086 </div>
1087 ) : waiting.length === 0 ? (
1088 <Empty>
1089 <p className="font-medium text-fg">No agent is at work right now</p>
1090 <p className="mt-1">Assign an issue to g1t and one starts on it in seconds. Its run shows here while it works.</p>
1091 </Empty>
1092 ) : (
1093 <List>
1094 {(shown as WaitingRow[]).map((row, index) => (
1095 <WaitingCard key={row.key} row={row} first={index === 0} />
1096 ))}
1097 </List>
1098 ))}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1099
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1100 {tab === "landed" &&
1101 loaded.perRepoLoaded &&
1102 (landed.length === 0 ? (
1103 <Empty>
1104 <p className="font-medium text-fg">Nothing has landed today yet</p>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1105 <p className="mt-1">
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1106 {week.total > 0
1107 ? `${plural(week.total, "change")} landed in the last 7 days.`
1108 : "Merged pull requests show up here the moment they land."}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1109 </p>
1110 </Empty>
1111 ) : (
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1112 <List>
1113 {(shown as LandedRow[]).map((row, index) => (
1114 <LandedCard key={row.key} row={row} first={index === 0} />
1115 ))}
1116 </List>
1117 ))}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1118
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1119 {rows.length > ROWS && (
1120 <div className="flex items-center justify-between border-t border-line px-4 py-2.5 text-xs text-muted sm:px-5">
1121 <span>
1122 Showing {shown.length} of {rows.length}
1123 </span>
1124 <Link
1125 to={link({ all: all ? null : "1" })}
1126 preventScrollReset
1127 className="inline-flex items-center gap-1 font-medium text-fg-soft hover:text-fg"
1128 >
1129 {all ? "Show fewer" : "See all"} <ChevronRight size={12} />
1130 </Link>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1131 </div>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1132 )}
1133 </section>
1134 </Card>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1135
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1136 <aside className="min-w-0 space-y-6">
Inbox: a bell in the top bar opens it beside the page, and /inbox holds it all1137 <InboxNeedsCard items={loaderData.inboxNeeds.items} total={loaderData.inboxNeeds.total} />
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1138 <Card asChild className="p-5">
1139 <section>
1140 <div className="flex items-center justify-between">
1141 <h2 className="text-base font-semibold tracking-tight">This week</h2>
1142 {workspace && (
1143 <Link to={`/${workspace}/-/agents`} className="text-xs text-muted hover:text-fg">
1144 Fleet
1145 </Link>
1146 )}
1147 </div>
1148 <div className="mt-4">{loaded.perRepoLoaded ? <WeekChart week={week} /> : <Unavailable what="The week" />}</div>
1149 {workspace && stats.weekCost > 0 && (
1150 <Link
1151 to={`/${workspace}/-/usage`}
1152 className="mt-4 flex items-center justify-between border-t border-line pt-3 text-xs text-muted hover:text-fg"
1153 >
Money is written one way. A single formatter turns millionths of a dollar into dollars, rounding half up on whole micros rather than on a float, so the same sum reads the same on every page: under a cent reads <$0.01 on a total and exactly nothing is $0.00, while the statement's lines, a session's receipt, the price book and an agent's effort costs carry up to four places where the fraction of a cent is the point; the six formatters that each rounded their own way are gone. This month is the calendar month in UTC from its first day to today everywhere, and billing counts the month's not-yet-closed usage in any range that reaches into the current month, so the top bar's pill, Spend, Home and Usage ask for the same days and get the same figure; Home now reads the usage report the others read instead of adding up statements. Usage's pending sentence says what of that usage the close will charge after the discount and included usage, which the billing API returns as pending_charged_micros. A reconciliation test holds the pill, Spend, Home and Usage to one number for one month. The usage and billing guide says how amounts are written and what this month means.1154 <span>Usage at price this week: {money(microsOf(stats.weekCost))}</span>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1155 <ChevronRight size={12} />
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1156 </Link>
1157 )}
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1158 </section>
1159 </Card>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1160
Mission control shows model usage, yours and the workspace's: tokens, cost, active days, cache share, each day, and the mix1161 {workspace && (
1162 <TokenUsagePanel
1163 workspace={loaderData.tokens.workspace}
1164 mine={loaderData.tokens.mine}
1165 usageHref={`/${workspace}/-/usage`}
1166 />
1167 )}
1168
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1169 <Card asChild className="scroll-mt-20 p-5">
1170 <section id="activity">
1171 <div className="flex items-center justify-between">
1172 <h2 className="text-base font-semibold tracking-tight">Activity</h2>
1173 {groups.length > 8 && (
1174 <Link
1175 to={`${link({ activity: everyActivity ? null : "all" })}#activity`}
1176 preventScrollReset
1177 className="inline-flex items-center gap-0.5 text-xs text-muted hover:text-fg"
1178 >
1179 {everyActivity ? "Less" : "All activity"} <ChevronRight size={12} />
1180 </Link>
1181 )}
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1182 </div>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1183 <p className="mt-1 flex items-center gap-3 text-[0.6875rem] text-faint">
1184 <span className="inline-flex items-center gap-1.5">
1185 <Avatar name="g1t" size={12} /> agents
1186 </span>
1187 <span className="inline-flex items-center gap-1.5">
1188 <Avatar name={viewer.username} size={12} /> people
1189 </span>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1190 </p>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1191 {!loaded.perRepoLoaded ? (
1192 <div className="mt-3">
1193 <Unavailable what="Activity" />
1194 </div>
1195 ) : feed.length === 0 ? (
1196 <p className="mt-3 text-sm leading-6 text-muted">
1197 Nothing has moved yet. Merges, deploys, checks, reviews and what agents learn show up here.
1198 </p>
1199 ) : (
1200 <ol className="mt-2 divide-y divide-line/70">
1201 {feed.map((group) => (
1202 <FeedLine key={group.id} group={group} titles={titles} />
1203 ))}
1204 </ol>
1205 )}
1206 </section>
1207 </Card>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1208
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.1209 <Card asChild className="p-5">
1210 <section>
1211 <h2 className="text-sm font-semibold">Connect your own agent</h2>
1212 <p className="mt-1.5 text-xs leading-5 text-muted">
1213 Add g1t to your coding agent. It signs in through your browser; there is no token to copy.
1214 </p>
1215 <AgentSetup className="mt-3" />
1216 <Link
1217 to="https://docs.g1t.sh/guides/bring-your-own-agent/"
1218 className="mt-3 inline-flex items-center gap-1 text-xs text-muted hover:text-fg"
1219 >
1220 How it works <ArrowRight size={12} />
1221 </Link>
1222 </section>
1223 </Card>
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms1224 </aside>
1225 </div>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1226 </main>
1227 );
1228}

This file's history is long; its oldest lines are credited to the oldest commit read.