Skip to content
2,055 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.

g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1import { Activity, BarChart3, Building2, MessagesSquare, Bell, BookMarked, BookOpen, Bookmark, Blocks, Bot, Box, Check, ChevronDown, ChevronLeft, ChevronRight, CircleDot, GripVertical, CircleUserRound, Code2, Compass, CreditCard, Fingerprint, GanttChart, Gauge, GitBranch, GitPullRequest, Globe, History, KanbanSquare, Keyboard, KeyRound, Layers, LayoutDashboard, LayoutGrid, LifeBuoy, ListTree, Lock, LogOut, Mail, Network, Package, PanelLeft, PlayCircle, Plug, Plus, Rocket, Search, ServerCog, Settings, Shapes, ShieldCheck, Scale, Smile, Sparkles, Sun, Ticket, TrendingUp, UserRoundKey, Users, UsersRound, Webhook, X, ArrowLeftRight } from "lucide-react";
2import { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar3import { Link, NavLink, useFetcher, useLocation, useNavigation, useRouteLoaderData, useSubmit } from "react-router";
A quicker settings slide: the same curve over 380ms4
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers5import { type Abilities, type ChatSidebarEntry, type InboxCounts, type WorkspaceAgent, type Membership, type Spike, type User, hasCodeAccess, mayCreateTeams, shownUsername } from "@g1t/contracts";
A quicker settings slide: the same curve over 380ms6
Not found and error pages have one main landmark: their own when signed out, the shell's when signed in7import { InMain } from "./landmark";
Usage, Billing settings and prepaid AI credit; fixes from the UX audit8import { CommandPalette, type PaletteCommand, PaletteKey, usePaletteShortcut } from "./command-palette";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.9import { NotificationsBell } from "./inbox";
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar10import { PinButton } from "./pin-button";
Merge branch 'worktree-agent-ae1299e92e4462012'11import { Hint } from "./ui/hint";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.12import { Sheet, SheetContent, SheetTitle } from "./ui/sheet";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas13import { StatusDot, useSiteStatus } from "./footer";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.14import { Logo } from "./logo";
Usage, Billing settings and prepaid AI credit; fixes from the UX audit15import { Avatar, SoonPill } from "./ui";
Fast pages, required checks on the branch, self-hosted runners, honest incidents16import { Skeleton } from "./ui/skeleton";
A quicker settings slide: the same curve over 380ms17import {
18 DropdownMenu,
19 DropdownMenuContent,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas20 DropdownMenuGroup,
A quicker settings slide: the same curve over 380ms21 DropdownMenuItem,
22 DropdownMenuLabel,
23 DropdownMenuSeparator,
24 DropdownMenuTrigger,
25} from "./ui/dropdown-menu";
Merge branch 'worktree-agent-ad7c6d88d93adc817'26import { type RoadmapItem, roadmapIn, roadmapItem } from "../lib/roadmap";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.27import { type ModeKey, SETTINGS_PAGES, modeOf, todayPath } from "../lib/workspace-nav";
Chat and workspace agents: channels, DMs and named agents you talk to28import { AgentsSidebar } from "./agents-mode";
29import { ChatSidebar } from "./chat/sidebar";
Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash.30import { FoliosSidebar } from "./folios/sidebar";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.31import { Dock, ShortcutsDialog, WorkspaceSwitcher, sidebarKeyLabel } from "./dock";
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)32import { G1tMark } from "./orchestrator";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.33import { BottomBar, isConversation, useVisualViewport } from "./mobile";
Chat and workspace agents: channels, DMs and named agents you talk to34import { useChatSidebar } from "./chat/actions";
35import { unreadTotals } from "../lib/chat";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look36import { SETTINGS_CAPABILITY, type ViewerAccess, seesSettings } from "../lib/access";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.37import { projectPages } from "../lib/chrome";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas38import { ACCOUNT_SETTINGS, type AccountSettingsPage, FIRST_SETTINGS_PAGE, accountSettingsPage } from "../lib/account-settings";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.39import { type PinnableApp, sidebarCookie } from "../lib/apps";
40import { REASON_FILTERS, inboxReason, inboxView } from "../lib/inbox";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas41import { GithubMark } from "./github";
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.42import { useInviteOnly } from "../lib/registration";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas43import { STATUS_URL, statusTitle } from "../lib/status";
Navigation: the workspace's own page with tabs, pins and recent in the sidebar44import { type ShortcutProject, movedPin, recentWith } from "../lib/pins";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas45import type { AccountMenuData } from "../routes/settings-menu-json";
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)46import { useLiveBadges } from "../lib/notify-client";
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers47import { OwnPresenceDot, OwnPresenceItems, StatusDialog } from "./presence";
A quicker settings slide: the same curve over 380ms48
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put49/**
50 * What the sidebar needs, worked out by the root loader. For a visitor who
51 * is not signed in there is no workspace, no projects and no usage: only
52 * the project being looked at, if they can see it.
53 */
A quicker settings slide: the same curve over 380ms54export type ShellData = {
55 /** The workspace the sidebar is about: the one being looked at, or their first. */
Workspace names and icons, and a component kit for every control56 workspace: Membership | null;
Navigation: the workspace's own page with tabs, pins and recent in the sidebar57 /** All its projects, by name, for the palette: `name` is the slug in their address. */
58 repos: ShortcutProject[];
59 /** The person's pinned projects in it, in their order (lib/pins.ts). */
60 pinned?: ShortcutProject[];
61 /** What they opened there last, latest first, leaving out the pinned. */
62 recent?: ShortcutProject[];
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look63 /** Repositories shared with them in workspaces they do not belong to. */
64 shared?: { namespace: string; name: string; isPrivate: boolean }[];
Projects: what a workspace builds and runs, first on every page65 /** The project being looked at, if any, whoever owns it. */
A quicker settings slide: the same curve over 380ms66 repo: {
67 namespace: string;
68 name: string;
69 member: boolean;
70 issues: number;
71 pulls: number;
72 } | null;
Billing accounts, terms and enterprises; g1t is no longer free73 /** Where the workspace stands against its usage limit, if billing is on. */
74 limit: {
75 exposureMicros: number;
76 ceilingMicros: number | null;
77 state: "ok" | "warning" | "stopped";
78 comped: boolean;
79 } | null;
Free while g1t is being built out; agents can check out their own forks80 /** Whether g1t charges nothing for now, while it is being built out. */
81 free?: boolean;
A quicker settings slide: the same curve over 380ms82 /** What its agents have cost since the start of the month. */
Usage while free is shown at cost; agents get rustfmt and clippy83 /** This month's usage: charged, or at cost while g1t is free. */
84 monthUsageMicros: number | null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look85 /** Whether new compute is paused (a spend spike or a hold), and whether the viewer can answer it. */
86 compute?: { paused: string | null; spike: Spike | null; owner: boolean } | null;
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.87 /** What is unread in their notifications, for the dock and the bell. Absent for a visitor. */
Inbox: a bell in the top bar opens it beside the page, and /inbox holds it all88 inbox?: InboxCounts | null;
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)89 /**
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.90 * Chat, for the dock's badge: what is unread, and the
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)91 * starred and latest conversations. Null when chat did not answer in time.
92 */
93 chat?: { unread: number; mentions: number; starred?: ChatSidebarEntry[]; recent?: ChatSidebarEntry[] } | null;
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.94 /** The workspace's agents, g1t first, for the Agents sidebar; null when not known. */
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)95 agents?: ShellAgent[] | null;
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.96 /** The apps this person pinned to their dock in the workspace (lib/apps.ts). */
97 pins?: PinnableApp[];
A quicker settings slide: the same curve over 380ms98};
99
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)100/** An agent as the shell lists it. */
101export type ShellAgent = Pick<
102 WorkspaceAgent,
103 "id" | "handle" | "display_name" | "avatar" | "avatar_seed" | "role" | "status" | "title" | "team" | "department" | "builtin"
104>;
105
A quicker settings slide: the same curve over 380ms106function SidebarLink({
107 to,
108 icon,
109 end,
110 count,
111 also,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look112 drill,
Merge branch 'worktree-agent-ad7c6d88d93adc817'113 current: lit,
A quicker settings slide: the same curve over 380ms114 children,
115}: {
116 to: string;
117 icon: ReactNode;
118 end?: boolean;
119 count?: number;
Projects: what a workspace builds and runs, first on every page120 /** Other path prefixes under which this link is the current one. */
121 also?: string | string[];
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look122 /** It opens a list of its own: a chevron says so, always or on hover. */
123 drill?: boolean | "hover";
Merge branch 'worktree-agent-ad7c6d88d93adc817'124 /** Whether it is the current row, when the list works that out itself. */
125 current?: boolean;
A quicker settings slide: the same curve over 380ms126 children: ReactNode;
127}) {
128 const { pathname } = useLocation();
129 return (
130 <NavLink
131 to={to}
132 end={end}
133 prefetch="intent"
134 className={({ isActive, isPending }) => {
Projects: what a workspace builds and runs, first on every page135 const current =
Merge branch 'worktree-agent-ad7c6d88d93adc817'136 lit ??
137 (isActive || [also ?? []].flat().some((prefix) => pathname === prefix || pathname.startsWith(prefix + "/")));
A quicker settings slide: the same curve over 380ms138 return `group flex h-8 items-center gap-2.5 rounded-md px-2 text-[0.8125rem] transition-colors ${
139 current
140 ? "bg-raised font-medium text-fg"
141 : isPending
142 ? "bg-raised/60 text-fg"
143 : "text-muted hover:bg-raised/60 hover:text-fg"
144 }`;
145 }}
146 >
147 <span className="shrink-0 text-faint group-hover:text-muted">{icon}</span>
148 <span className="min-w-0 grow truncate">{children}</span>
149 {count != null && count > 0 && (
150 <span className="rounded bg-line px-1.5 text-[0.6875rem] tabular-nums text-muted">
151 {count}
152 </span>
153 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look154 {drill && (
155 <ChevronRight
156 size={14}
157 aria-hidden="true"
158 className={`-mr-0.5 shrink-0 text-faint transition-opacity ${drill === "hover" ? "opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" : ""}`}
159 />
160 )}
A quicker settings slide: the same curve over 380ms161 </NavLink>
162 );
163}
164
Pull requests say where they are live; the project menu shows what is coming165/**
166 * Something a project will have, shown where it will live so people can
167 * see where g1t is going. Not a link: nothing is behind it yet.
168 */
169function SidebarSoon({ icon, children, about }: { icon: ReactNode; children: ReactNode; about: string }) {
170 return (
Merge branch 'worktree-agent-ae1299e92e4462012'171 <Hint label={about} side="right">
172 <div aria-disabled="true" className="flex h-8 cursor-default items-center gap-2.5 rounded-md px-2 text-[0.8125rem] text-faint">
173 <span className="shrink-0 opacity-70">{icon}</span>
174 <span className="grow truncate">{children}</span>
175 <span className="sr-only">{about}</span>
176 <SoonPill />
177 </div>
178 </Hint>
Pull requests say where they are live; the project menu shows what is coming179 );
180}
181
The project menu opens by section, and the workspace has its own panel182/**
A flat project menu with Code first, views as tabs, and Stripe for every owner183 * A page that is coming, as a link to its roadmap page: faint, with Soon,
184 * and marked current on any of its section's Soon pages.
The project menu opens by section, and the workspace has its own panel185 */
A flat project menu with Code first, views as tabs, and Stripe for every owner186function SidebarSoonLink({
The project menu opens by section, and the workspace has its own panel187 to,
188 also,
A flat project menu with Code first, views as tabs, and Stripe for every owner189 icon,
190 about,
Merge branch 'worktree-agent-ad7c6d88d93adc817'191 current: lit,
The project menu opens by section, and the workspace has its own panel192 children,
193}: {
194 to: string;
A flat project menu with Code first, views as tabs, and Stripe for every owner195 also?: string[];
196 icon: ReactNode;
197 about: string;
Merge branch 'worktree-agent-ad7c6d88d93adc817'198 /** Whether it is the current row, when the list works that out itself. */
199 current?: boolean;
The project menu opens by section, and the workspace has its own panel200 children: ReactNode;
201}) {
202 const { pathname } = useLocation();
203 return (
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero204 // The hint wraps a plain box: Radix's asChild merges className as a
205 // string, which would break NavLink's className function.
Merge branch 'worktree-agent-ae1299e92e4462012'206 <Hint label={about} side="right">
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero207 <div>
The project menu opens by section, and the workspace has its own panel208 <NavLink
209 to={to}
210 prefetch="intent"
A flat project menu with Code first, views as tabs, and Stripe for every owner211 className={({ isActive }) => {
Merge branch 'worktree-agent-ad7c6d88d93adc817'212 const current = lit ?? (isActive || (also ?? []).some((prefix) => pathname === prefix || pathname.startsWith(prefix + "/")));
A flat project menu with Code first, views as tabs, and Stripe for every owner213 return `group flex h-8 items-center gap-2.5 rounded-md px-2 text-[0.8125rem] transition-colors ${
214 current ? "bg-raised font-medium text-fg" : "text-faint hover:bg-raised/60 hover:text-muted"
The project menu opens by section, and the workspace has its own panel215 }`;
216 }}
217 >
A flat project menu with Code first, views as tabs, and Stripe for every owner218 <span className="shrink-0 opacity-80">{icon}</span>
The project menu opens by section, and the workspace has its own panel219 <span className="min-w-0 grow truncate">{children}</span>
Usage, Billing settings and prepaid AI credit; fixes from the UX audit220 <SoonPill />
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales221 </NavLink>
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero222 </div>
Merge branch 'worktree-agent-ae1299e92e4462012'223 </Hint>
The project menu opens by section, and the workspace has its own panel224 );
225}
226
A flat project menu with Code first, views as tabs, and Stripe for every owner227/** Icons for what spans projects. */
228const WORKSPACE_ICONS: Record<string, ReactNode> = {
229 board: <KanbanSquare size={15} />,
230 roadmap: <GanttChart size={15} />,
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member231 teams: <UsersRound size={15} />,
A flat project menu with Code first, views as tabs, and Stripe for every owner232 packages: <Package size={15} />,
233 fleet: <Bot size={15} />,
234};
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales235
A flat project menu with Code first, views as tabs, and Stripe for every owner236/** The Soon pages of a section, as paths, so its link is current on them. */
237function soonPaths(base: string, section: RoadmapItem["section"]): string[] {
238 return roadmapIn(section).map((item) => `${base}/soon/${item.key}`);
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales239}
240
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look241function SidebarGroup({
242 title,
243 action,
244 className = "",
245 children,
246}: {
247 title: string;
248 action?: ReactNode;
249 className?: string;
250 children: ReactNode;
251}) {
A quicker settings slide: the same curve over 380ms252 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look253 <section className={className}>
A quicker settings slide: the same curve over 380ms254 <div className="mb-1 flex h-6 items-center justify-between px-2">
255 <h2 className="text-xs font-medium text-faint">{title}</h2>
256 {action}
257 </div>
258 <div className="space-y-px">{children}</div>
259 </section>
260 );
261}
262
Workspace names and icons, and a component kit for every control263/** What a workspace is called where people read it: its display name, else its slug. */
264function displayName(membership: Membership): string {
265 return membership.name?.trim() || membership.slug;
A quicker settings slide: the same curve over 380ms266}
267
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas268/**
269 * The fine print, as one quiet row at the foot of the account menu and the
270 * visitor's panel: each link a full-height target, left-aligned. In the
271 * menu each is a menu item, so the arrow keys reach it.
272 */
273const LEGAL_LINKS: [string, string][] = [
274 ["Policies", "/policies"],
275 ["Privacy", "/policies/privacy"],
276 ["Security", "/security"],
277];
278const LEGAL_LINK = "flex h-7 items-center rounded px-1.5 text-xs text-faint outline-none transition-colors";
279
280function MenuLegalRow() {
281 return (
282 <div role="group" aria-label="Legal" className="flex items-center gap-0.5 px-0.5 pt-0.5">
283 {LEGAL_LINKS.map(([label, to], index) => (
284 <span key={to} className="flex items-center gap-0.5">
285 {index > 0 && (
286 <span aria-hidden="true" className="text-[0.625rem] text-line-strong">
287 ·
288 </span>
289 )}
290 <DropdownMenuItem asChild className={`${LEGAL_LINK} py-0 data-highlighted:bg-line data-highlighted:text-fg`}>
291 <Link to={to}>{label}</Link>
292 </DropdownMenuItem>
293 </span>
294 ))}
295 </div>
296 );
297}
298
299/** Status's row: the live dot and two or three words, fetched when the menu opens. */
300function StatusSummary({ open }: { open: boolean }) {
301 const status = useSiteStatus(open);
302 const words = statusTitle(status);
303 return (
304 <span className="ml-auto flex min-w-0 items-center gap-1.5 pl-2 text-xs text-faint">
305 {/* The words say it; the dot's own words for screen readers would repeat them. */}
306 <span aria-hidden="true" className="flex">
307 <StatusDot state={status?.overall.state ?? null} />
308 </span>
Fast pages, required checks on the branch, self-hosted runners, honest incidents309 {words ? <span className="truncate">{words}</span> : <Skeleton className="h-3 w-20" />}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas310 </span>
311 );
312}
313
314/** A menu row: an icon, words, and whatever sits at its end. */
315const MENU_ROW = "h-9 gap-2.5 px-2.5 text-[0.8125rem]";
316
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.317/**
318 * Your account, at the foot of the dock (or in the header, before you have
319 * a workspace): who you are and your status, your profile and settings,
320 * and help: the documentation, support, status and the keyboard's
321 * shortcuts; then signing out and the fine print.
322 */
323function AccountMenu({ user, side = "right" }: { user: User; side?: "right" | "bottom" }) {
A quicker settings slide: the same curve over 380ms324 const submit = useSubmit();
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas325 const [open, setOpen] = useState(false);
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.326 const [keys, setKeys] = useState(false);
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers327 // Your status's dialog: outside the menu, so the menu closes behind it.
328 const [editing, setEditing] = useState(false);
Fast pages, required checks on the branch, self-hosted runners, honest incidents329 // Name, primary address and invites left: asked for once, as soon as the
330 // pointer or focus reaches the button, so they are there when it opens.
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas331 const details = useFetcher<AccountMenuData | null>({ key: "account-menu" });
Fast pages, required checks on the branch, self-hosted runners, honest incidents332 const prefetch = () => {
333 if (details.state === "idle" && details.data === undefined) details.load("/settings/menu.json");
334 };
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas335 useEffect(() => {
Fast pages, required checks on the branch, self-hosted runners, honest incidents336 if (open) prefetch();
337 // eslint-disable-next-line react-hooks/exhaustive-deps
338 }, [open]);
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas339 const me = details.data ?? null;
Fast pages, required checks on the branch, self-hosted runners, honest incidents340 // Still on its way: shapes where the words will be, the same size.
341 const loading = details.data === undefined && details.state !== "idle";
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)342 // While anyone can sign up, listed once the data says there are invites to look back on.
343 const invitesListed = useInviteOnly() || me?.invites_page === true;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas344 const profile = `/u/${user.username}`;
A quicker settings slide: the same curve over 380ms345 return (
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers346 <>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas347 <DropdownMenu open={open} onOpenChange={setOpen}>
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.348 {/* The avatar alone, with a dot that says how others see you (components/presence.tsx). */}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas349 <DropdownMenuTrigger
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers350 aria-label={`Account menu for ${shownUsername(user)}`}
Fast pages, required checks on the branch, self-hosted runners, honest incidents351 onPointerEnter={prefetch}
352 onFocus={prefetch}
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.353 className="relative flex rounded-full outline-none transition-transform hover:scale-[1.04] focus-visible:ring-2 focus-visible:ring-accent data-[state=open]:ring-2 data-[state=open]:ring-line-strong"
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas354 >
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.355 <Avatar name={user.username} image={user.avatar} size={side === "right" ? 32 : 28} />
356 <OwnPresenceDot ring={side === "right" ? "var(--color-dock)" : "var(--color-bg)"} className="absolute -right-0.5 -bottom-0.5" />
A quicker settings slide: the same curve over 380ms357 </DropdownMenuTrigger>
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.358 <DropdownMenuContent align="end" side={side} sideOffset={side === "right" ? 14 : 6} collisionPadding={8} className="w-[17.5rem] p-1.5">
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas359 {/* Who is signed in, and a way to their profile. */}
360 <DropdownMenuItem asChild className="gap-3 px-2 py-2">
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers361 <Link to={profile} aria-label={`${me?.name ?? shownUsername(user)} (@${shownUsername(user)}), your profile`}>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas362 <Avatar name={user.username} image={user.avatar} size={36} />
Fast pages, required checks on the branch, self-hosted runners, honest incidents363 <span className="flex min-w-0 grow flex-col leading-tight" aria-busy={loading}>
364 {loading ? (
365 <Skeleton className="my-[0.1875rem] h-3.5 w-28" />
366 ) : (
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers367 <span className="truncate text-sm font-medium text-fg">{me?.name ?? shownUsername(user)}</span>
Fast pages, required checks on the branch, self-hosted runners, honest incidents368 )}
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers369 <span className="truncate font-mono text-xs text-muted">@{shownUsername(user)}</span>
Fast pages, required checks on the branch, self-hosted runners, honest incidents370 {loading ? (
371 <Skeleton className="mt-1 h-3 w-40" />
372 ) : (
373 me?.email && <span className="mt-0.5 truncate text-xs text-faint">{me.email}</span>
374 )}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas375 </span>
A quicker settings slide: the same curve over 380ms376 </Link>
377 </DropdownMenuItem>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas378 <DropdownMenuSeparator className="my-1.5" />
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers379 {/* Your status, away, and pausing notifications. */}
380 <DropdownMenuGroup>
381 <OwnPresenceItems className="min-h-9 py-1.5 text-[0.8125rem]" onEdit={() => setEditing(true)} />
382 </DropdownMenuGroup>
383 <DropdownMenuSeparator className="my-1.5" />
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas384 <DropdownMenuGroup>
385 <DropdownMenuItem asChild className={MENU_ROW}>
386 <Link to={profile}>
387 <CircleUserRound />
388 Your profile
389 </Link>
390 </DropdownMenuItem>
391 <DropdownMenuItem asChild className={MENU_ROW}>
392 <Link to={FIRST_SETTINGS_PAGE}>
393 <Settings />
394 Your settings
395 </Link>
396 </DropdownMenuItem>
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)397 {invitesListed && (
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas398 <DropdownMenuItem asChild className={MENU_ROW}>
399 <Link to="/settings/invites">
400 <Ticket />
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)401 {ACCOUNT_SETTINGS.invites.title}
Fast pages, required checks on the branch, self-hosted runners, honest incidents402 {loading && <Skeleton className="ml-auto h-4 w-12 rounded-full" />}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas403 {me?.invites_left != null && (
404 <span className="ml-auto rounded-full bg-line px-1.5 text-[0.6875rem] tabular-nums text-muted">
405 {me.invites_left} left
406 </span>
407 )}
408 </Link>
409 </DropdownMenuItem>
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)410 )}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas411 </DropdownMenuGroup>
412 <DropdownMenuSeparator className="my-1.5" />
413 <DropdownMenuGroup>
414 <DropdownMenuItem asChild className={MENU_ROW}>
415 <a href="https://docs.g1t.sh/">
416 <BookOpen />
417 Documentation
418 </a>
419 </DropdownMenuItem>
420 <DropdownMenuItem asChild className={MENU_ROW}>
421 <Link to="/support">
422 <LifeBuoy />
423 Support
424 </Link>
425 </DropdownMenuItem>
426 <DropdownMenuItem asChild className={MENU_ROW}>
427 <a href={STATUS_URL}>
428 <Activity />
429 Status
430 <StatusSummary open={open} />
431 </a>
432 </DropdownMenuItem>
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.433 <DropdownMenuItem className={MENU_ROW} onSelect={() => setKeys(true)}>
434 <Keyboard />
435 Keyboard shortcuts
436 <PaletteKey className="ml-auto font-sans text-xs text-faint" />
437 </DropdownMenuItem>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas438 </DropdownMenuGroup>
439 <DropdownMenuSeparator className="my-1.5" />
A quicker settings slide: the same curve over 380ms440 {/* Submitted from here: the menu closes on select, and a button
441 that has left the page cannot submit a form. */}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas442 <DropdownMenuItem className={MENU_ROW} onSelect={() => submit(null, { method: "post", action: "/logout" })}>
A quicker settings slide: the same curve over 380ms443 <LogOut />
444 Sign out
445 </DropdownMenuItem>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas446 <DropdownMenuSeparator className="my-1.5" />
447 <MenuLegalRow />
A quicker settings slide: the same curve over 380ms448 </DropdownMenuContent>
449 </DropdownMenu>
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers450 <StatusDialog open={editing} onOpenChange={setEditing} />
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.451 <ShortcutsDialog open={keys} onOpenChange={setKeys} />
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers452 </>
A quicker settings slide: the same curve over 380ms453 );
454}
455
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look456/**
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar457 * A workspace's settings pages, which the sidebar drills into: how it is
458 * set up and connected (guardrails, secrets, runners, integrations,
459 * webhooks), what it pays, its repositories, tokens and record. The main
460 * list keeps the places work happens and who belongs; every member can
461 * still open these.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look462 */
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar463const SETTINGS_PAGE =
Merge branch 'worktree-agent-ad7c6d88d93adc817'464 new RegExp(`^/([^/]+)/-/(${SETTINGS_PAGES.join("|")})(/|$)`);
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look465/** A project's settings pages, which the project's menu drills into. */
Project settings move into the sidebar, grouped, with a heading per page466const REPO_SETTINGS_PAGE = /^\/([^/]+)\/([^/-][^/]*)\/settings(\/|$)/;
A quicker settings slide: the same curve over 380ms467
468/**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look469 * The sidebar's lists are a stack, the way a phone pushes a screen: one
470 * drilled into slides in from the right over the full width, while the one
471 * it covers drifts a quarter of the way left and fades, both on one long
Sidebar: the panels really slide472 * ease-out, the fade quicker than the move so the two never blur together.
473 * Going back reverses it.
A quicker settings slide: the same curve over 380ms474 */
Sidebar: no settings flash on the way into a repository, and a better slide475const LAYER =
Sidebar: the panels really slide476 "absolute inset-0 [transition:translate_380ms_cubic-bezier(0.32,0.72,0,1),opacity_220ms_ease-out] will-change-[translate,opacity] motion-reduce:transition-none";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look477/** One list, filling its layer. */
Sidebar: no settings flash on the way into a repository, and a better slide478const PANEL = "h-full overflow-y-auto px-2 pb-4";
A quicker settings slide: the same curve over 380ms479
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look480/** One list in the stack: what it is, and its rows. */
481type Level = { key: string; node: ReactNode };
482
483/** True once the page has hydrated, so what the server drew never animates in. */
484function useHydrated(): boolean {
485 const [hydrated, setHydrated] = useState(false);
486 useEffect(() => setHydrated(true), []);
487 return hydrated;
488}
489
490/**
491 * Drilling in and out of the sidebar's lists. `trail` is the way from the
492 * main list to the one shown, worked out from the address, so a link
493 * straight to a settings page opens the sidebar already drilled in, and
494 * leaving it comes back out. Lists deeper than the one shown stay in
495 * place, off to the right, so going back slides them away rather than
496 * dropping them. Moving to a list at the same depth (a workspace's settings
497 * to a project) fades the new one in where it is.
498 */
499function Drill({ trail }: { trail: Level[] }) {
500 const depth = trail.length - 1;
501 const hydrated = useHydrated();
502 const stack = useRef<Level[]>(trail);
503 const before = stack.current;
504 const within = trail.every((level, index) => before[index]?.key === level.key);
505 stack.current = within ? [...trail, ...before.slice(trail.length)] : trail;
506 const levels = stack.current;
507 // What was showing last time, to tell drilling in from moving across.
508 const shown = useRef({ depth, keys: levels.map((level) => level.key) });
509 useEffect(() => {
510 shown.current = { depth, keys: levels.map((level) => level.key) };
511 });
A quicker settings slide: the same curve over 380ms512 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look513 <div className="relative min-h-0 grow overflow-hidden">
514 {levels.map((level, index) => {
515 const current = index === depth;
516 const place =
517 index < depth
518 ? "pointer-events-none -translate-x-1/4 opacity-0"
519 : current
520 ? "translate-x-0 opacity-100"
521 : "pointer-events-none translate-x-full opacity-0";
522 // A list that was not there before arrives: from the right when
523 // drilling in, in place when moving across.
524 const arriving = hydrated && current && !shown.current.keys.includes(level.key);
525 const enter = arriving
526 ? depth > shown.current.depth
527 ? "starting:translate-x-full starting:opacity-0"
528 : "starting:opacity-0"
529 : "";
530 return (
531 <div key={level.key} className={`${LAYER} ${place} ${enter}`} inert={!current} aria-hidden={!current || undefined}>
532 {level.node}
533 </div>
534 );
535 })}
536 </div>
537 );
538}
539
540/**
541 * The row at the top of a list drilled into: the list's name, which goes
542 * back out, and what it belongs to, faint at the end.
543 */
544function BackRow({ to, label, context }: { to: string; label: ReactNode; context?: ReactNode }) {
545 return (
546 <Link
547 to={to}
548 prefetch="intent"
549 className="group mt-3 flex h-8 items-center gap-1.5 rounded-md pr-2 pl-1 text-[0.8125rem] font-medium text-fg transition-colors hover:bg-raised/60"
A quicker settings slide: the same curve over 380ms550 >
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look551 <ChevronLeft size={16} className="shrink-0 text-faint transition-transform group-hover:-translate-x-0.5 group-hover:text-muted" />
552 <span className="min-w-0 shrink-0 truncate">{label}</span>
553 {context && (
554 <span className="ml-auto min-w-0 truncate pl-2 font-mono text-[0.6875rem] font-normal text-faint">{context}</span>
555 )}
556 </Link>
557 );
558}
559
560/** A thin rule between groups of a list. */
561function Rule() {
562 return <div role="separator" className="mx-2 my-2.5 h-px bg-line" />;
563}
564
Navigation: the workspace's own page with tabs, pins and recent in the sidebar565/** A quiet heading inside a group: Pinned, Recent. */
566function SidebarSubhead({ children }: { children: ReactNode }) {
567 return <h3 className="px-2 pt-1.5 pb-0.5 text-[0.6875rem] font-medium tracking-wide text-faint">{children}</h3>;
568}
569
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look570/**
Navigation: the workspace's own page with tabs, pins and recent in the sidebar571 * The workspace's projects as the sidebar keeps them, however many there
572 * are: the person's pins in their order, what they opened last, and the
573 * way to all of them. Pins move by dragging, or with Alt and the arrow
574 * keys; the projects service keeps the order.
575 */
Merge branch 'worktree-agent-ad7c6d88d93adc817'576function SidebarProjects({ slug, shell, current }: { slug: string; shell: ShellData; current: boolean }) {
Navigation: the workspace's own page with tabs, pins and recent in the sidebar577 const reorder = useFetcher({ key: `pins:${slug}` });
578 const saved = shell.pinned ?? [];
579 // While a new order is on its way, it shows as made.
580 const asked = reorder.formData?.get("intent") === "reorder" ? reorder.formData.getAll("slug").map(String) : null;
581 const pinned = asked
582 ? asked.map((name) => saved.find((project) => project.name === name)).filter((project): project is ShortcutProject => project != null)
583 : saved;
584 const active = shell.repo ? { namespace: shell.repo.namespace, name: shell.repo.name, isPrivate: false } : null;
585 const recent = recentWith(shell.recent ?? [], pinned, active, slug);
586 const [dragging, setDragging] = useState<number | null>(null);
587 const move = (from: number, by: number) => {
588 const next = movedPin(pinned, from, by);
589 if (!next) return;
590 const form = new FormData();
591 form.set("intent", "reorder");
592 for (const project of next) form.append("slug", project.name);
593 reorder.submit(form, { method: "post", action: `/${slug}/-/pins` });
594 };
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar595 // Each row pins or unpins in place: the pin shows on hover or focus, and
596 // stays shown on a pinned row's hover so it reads as "unpin".
597 const row = (project: ShortcutProject, isPinned: boolean) => (
598 <div className="group/row relative">
599 <SidebarLink to={`/${project.namespace}/${project.name}`} icon={project.isPrivate ? <Lock size={15} /> : <Box size={15} />} drill="hover">
600 <span className="block truncate pr-6">{project.title ?? project.name}</span>
601 </SidebarLink>
602 <PinButton
603 workspace={slug}
604 slug={project.name}
605 name={project.title ?? project.name}
606 pinned={isPinned}
607 small
608 className="absolute top-1/2 right-6 -translate-y-1/2 opacity-0 transition-opacity group-hover/row:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100"
609 />
610 </div>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar611 );
612 return (
613 <SidebarGroup
614 title="Projects"
615 action={
616 <Link to={`/new?workspace=${slug}`} aria-label="New project" className="rounded p-0.5 text-faint hover:bg-raised hover:text-fg">
617 <Plus size={13} />
618 </Link>
619 }
620 >
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar621 {/* Only there once something is pinned: each row below has its own pin. */}
622 {pinned.length > 0 && (
623 <>
624 <SidebarSubhead>Pinned</SidebarSubhead>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar625 <ul aria-label="Pinned projects" className="space-y-px">
626 {pinned.map((project, index) => (
627 <li
628 key={project.name}
629 draggable={pinned.length > 1}
630 onDragStart={(event) => {
631 setDragging(index);
632 event.dataTransfer.effectAllowed = "move";
633 }}
634 onDragOver={(event) => {
635 if (dragging != null) event.preventDefault();
636 }}
637 onDrop={(event) => {
638 event.preventDefault();
639 if (dragging != null && dragging !== index) move(dragging, index - dragging);
640 setDragging(null);
641 }}
642 onDragEnd={() => setDragging(null)}
643 onKeyDown={(event) => {
644 if (!event.altKey || (event.key !== "ArrowUp" && event.key !== "ArrowDown")) return;
645 event.preventDefault();
646 move(index, event.key === "ArrowUp" ? -1 : 1);
647 }}
648 className={`group/pin relative ${dragging === index ? "opacity-50" : ""}`}
649 >
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar650 {row(project, true)}
Navigation: the workspace's own page with tabs, pins and recent in the sidebar651 {pinned.length > 1 && (
Merge branch 'worktree-agent-ae1299e92e4462012'652 <Hint label="Drag, or Alt and an arrow key, to reorder" side="right">
653 <span className="absolute top-1/2 -left-1.5 -translate-y-1/2 cursor-grab text-faint opacity-0 transition-opacity group-hover/pin:opacity-100">
654 <GripVertical size={12} aria-hidden="true" />
655 </span>
656 </Hint>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar657 )}
658 </li>
659 ))}
660 </ul>
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar661 </>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar662 )}
663 {recent.length > 0 && (
664 <>
665 <SidebarSubhead>Recent</SidebarSubhead>
666 {recent.map((project) => (
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar667 <div key={`${project.namespace}/${project.name}`}>{row(project, false)}</div>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar668 ))}
669 </>
670 )}
671 <div className="pt-1">
Merge branch 'worktree-agent-ad7c6d88d93adc817'672 <SidebarLink to={`/${slug}/-/projects`} icon={<LayoutGrid size={15} />} count={shell.repos.length} current={current}>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar673 All projects
674 </SidebarLink>
675 </div>
676 </SidebarGroup>
677 );
678}
679
Merge branch 'worktree-agent-ad7c6d88d93adc817'680/** Insights, coming: the workspace's own page says what it will be. */
681const INSIGHTS = roadmapItem("insights");
682
Sidebar: no settings flash on the way into a repository, and a better slide683/**
684 * What the repository menu needs. Known from the address before the page's
685 * data arrives, so the menu is right from the first frame; the counts fill
686 * in once it does.
687 */
688type MenuRepo = {
689 namespace: string;
690 name: string;
691 member: boolean;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look692 /** Whether they see its settings; from the repository's page once it loads. */
693 settings?: boolean;
694 /** What they may do there, once the repository's page loads. */
695 can?: Abilities;
Sidebar: no settings flash on the way into a repository, and a better slide696 issues?: number;
697 pulls?: number;
698};
699
700function sameRepo(a: { namespace: string; name: string } | null, b: { namespace: string; name: string } | null) {
701 return (
702 a != null &&
703 b != null &&
704 a.namespace.toLowerCase() === b.namespace.toLowerCase() &&
705 a.name.toLowerCase() === b.name.toLowerCase()
706 );
707}
A repository has its own sidebar, as settings do708
709/**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look710 * A project's own list, drilled into while you are in it: everything about
711 * the project, running and its code, and nothing else, with the way back
712 * out to all of them.
A repository has its own sidebar, as settings do713 */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put714function RepoMenu({
715 repo,
716 isPrivate,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look717 back,
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put718}: {
719 repo: MenuRepo;
720 isPrivate: boolean;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look721 /** Where the way back leads: the workspace's projects, mission control, or Explore. */
722 back: { to: string; label: string };
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put723}) {
A repository has its own sidebar, as settings do724 const base = `/${repo.namespace}/${repo.name}`;
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put725 // What a member sees, and what everyone who can see the project does.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look726 const shows = new Set(projectPages(repo.member, repo.can));
A repository has its own sidebar, as settings do727 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look728 <nav aria-label={`${repo.namespace}/${repo.name}`} className={PANEL}>
729 <BackRow to={back.to} label={back.label} />
Merge branch 'worktree-agent-ae1299e92e4462012'730 <Hint label="Overview" side="right">
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero731 <div>
A flat project menu with Code first, views as tabs, and Stripe for every owner732 <NavLink
A repository has its own sidebar, as settings do733 to={base}
A flat project menu with Code first, views as tabs, and Stripe for every owner734 end
Fast pages, required checks on the branch, self-hosted runners, honest incidents735 prefetch="intent"
A flat project menu with Code first, views as tabs, and Stripe for every owner736 className={({ isActive }) =>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look737 `mt-2 flex items-center gap-2 rounded-md px-2 py-1.5 transition-colors ${isActive ? "bg-raised" : "hover:bg-raised/60"}`
A flat project menu with Code first, views as tabs, and Stripe for every owner738 }
A repository has its own sidebar, as settings do739 >
740 <span className="flex size-6 shrink-0 items-center justify-center rounded-md bg-raised text-muted ring-1 ring-line">
Projects: what a workspace builds and runs, first on every page741 {isPrivate ? <Lock size={13} /> : <Box size={13} />}
A repository has its own sidebar, as settings do742 </span>
743 <span className="min-w-0 truncate font-mono text-[0.8125rem]">
744 <span className="text-faint">{repo.namespace}/</span>
745 <span className="font-semibold text-fg">{repo.name}</span>
746 </span>
A flat project menu with Code first, views as tabs, and Stripe for every owner747 </NavLink>
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero748 </div>
Merge branch 'worktree-agent-ae1299e92e4462012'749 </Hint>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look750 {/* A project's pages, in the order people use them. A page with more
751 than one view shows them as tabs across its top. */}
752 <Rule />
753 <div className="space-y-px">
Compare: any two branches, the commits one has that the other does not, and the diff, with Open a pull request754 <SidebarLink to={`${base}/code`} also={[`${base}/tree`, `${base}/blob`, `${base}/commits`, `${base}/commit`, `${base}/branches`, `${base}/tags`, `${base}/compare`, ...soonPaths(base, "Code")]} icon={<Code2 size={15} />}>
A flat project menu with Code first, views as tabs, and Stripe for every owner755 Code
756 </SidebarLink>
Usage, Billing settings and prepaid AI credit; fixes from the UX audit757 <SidebarLink to={`${base}/issues`} also={[`${base}/plans`, `${base}/milestones`, `${base}/labels`, ...soonPaths(base, "Issues")]} icon={<CircleDot size={15} />} count={repo.issues}>
A flat project menu with Code first, views as tabs, and Stripe for every owner758 Issues
759 </SidebarLink>
760 <SidebarLink to={`${base}/pulls`} also={[`${base}/pull`, `${base}/queue`]} icon={<GitPullRequest size={15} />} count={repo.pulls}>
761 Pull requests
762 </SidebarLink>
Agents and memory, checks and conflicts, profiles, slug renames, custom domains763 <SidebarLink to={`${base}/agents`} also={[`${base}/sessions`, `${base}/memory`, ...soonPaths(base, "Agents")]} icon={<Bot size={15} />}>
A flat project menu with Code first, views as tabs, and Stripe for every owner764 Agents
Agents and memory, checks and conflicts, profiles, slug renames, custom domains765 </SidebarLink>
A flat project menu with Code first, views as tabs, and Stripe for every owner766 <SidebarLink to={`${base}/actions`} icon={<PlayCircle size={15} />}>
767 Workflows
Projects: what a workspace builds and runs, first on every page768 </SidebarLink>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look769 </div>
770 <Rule />
771 <div className="space-y-px">
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put772 {shows.has("deployments") ? (
A flat project menu with Code first, views as tabs, and Stripe for every owner773 <SidebarLink to={`${base}/deployments`} also={soonPaths(base, "Deployments")} icon={<Rocket size={15} />}>
774 Deployments
775 </SidebarLink>
776 ) : null}
Observability gets its own page; tabs never overflow777 <SidebarSoonLink to={`${base}/soon/logs`} also={soonPaths(base, "Observability")} icon={<Activity size={15} />} about="Logs, errors, uptime and analytics of the project's deployed apps.">
778 Observability
A flat project menu with Code first, views as tabs, and Stripe for every owner779 </SidebarSoonLink>
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put780 {shows.has("security") ? (
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API781 <SidebarLink to={`${base}/security`} also={soonPaths(base, "Security")} icon={<ShieldCheck size={15} />}>
782 Security
783 </SidebarLink>
784 ) : null}
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97785 <SidebarLink
786 to={`${base}/contributors`}
787 also={[`${base}/activity`, `${base}/stargazers`, ...soonPaths(base, "Insights")]}
788 icon={<BarChart3 size={15} />}
789 >
A flat project menu with Code first, views as tabs, and Stripe for every owner790 Insights
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97791 </SidebarLink>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look792 </div>
793 {(repo.settings ?? shows.has("settings")) && (
794 <>
795 <Rule />
796 <SidebarLink to={`${base}/settings`} icon={<Settings size={15} />} drill>
A flat project menu with Code first, views as tabs, and Stripe for every owner797 Settings
798 </SidebarLink>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look799 </>
800 )}
A repository has its own sidebar, as settings do801 </nav>
802 );
803}
804
Project settings move into the sidebar, grouped, with a heading per page805/**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look806 * A project's settings, drilled into from its list: what is about running
807 * it, then its agents, then its code and who can reach it. The way back
808 * leads to the project.
Project settings move into the sidebar, grouped, with a heading per page809 */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look810function RepoSettingsMenu({ repo }: { repo: MenuRepo }) {
Project settings move into the sidebar, grouped, with a heading per page811 const base = `/${repo.namespace}/${repo.name}`;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look812 // Each page shows to the roles that can use it, once the role is known.
813 const shows = (page: string) => !repo.can || repo.can[SETTINGS_CAPABILITY[page] ?? "administer"];
814 const running = shows("deployments");
815 const agents = shows("agents") || shows("guardrails");
Project settings move into the sidebar, grouped, with a heading per page816 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look817 <nav aria-label={`${repo.namespace}/${repo.name} settings`} className={PANEL}>
818 <BackRow to={base} label="Settings" context={`${repo.namespace}/${repo.name}`} />
819 {shows("") && (
820 <div className="mt-2 space-y-px">
821 <SidebarLink to={`${base}/settings`} end icon={<Settings size={15} />}>
822 General
823 </SidebarLink>
824 </div>
825 )}
826 {running && (
827 <>
828 {shows("") && <Rule />}
829 <div className={shows("") ? "space-y-px" : "mt-2 space-y-px"}>
830 <SidebarLink to={`${base}/settings/deployments`} icon={<Rocket size={15} />}>
831 Deployments
832 </SidebarLink>
833 <SidebarLink to={`${base}/settings/domains`} icon={<Globe size={15} />}>
834 Domains
835 </SidebarLink>
836 </div>
837 </>
838 )}
839 {agents && (
840 <>
841 <Rule />
842 <div className="space-y-px">
843 {shows("agents") && (
844 <SidebarLink to={`${base}/settings/agents`} icon={<Bot size={15} />}>
845 Agents
846 </SidebarLink>
847 )}
848 {shows("guardrails") && (
849 <SidebarLink to={`${base}/settings/guardrails`} icon={<ShieldCheck size={15} />}>
850 Guardrails
851 </SidebarLink>
852 )}
853 </div>
854 </>
855 )}
856 <Rule />
857 <div className="space-y-px">
858 {shows("repository") && (
859 <SidebarLink to={`${base}/settings/repository`} icon={<BookMarked size={15} />}>
860 Repository
861 </SidebarLink>
862 )}
Merge branch 'mirroring' into artifacts-mode863 {shows("mirroring") && (
864 <SidebarLink to={`${base}/settings/mirroring`} icon={<ArrowLeftRight size={15} />}>
865 Mirroring
866 </SidebarLink>
867 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look868 {shows("access") && (
869 <SidebarLink to={`${base}/settings/access`} icon={<Users size={15} />}>
870 Access
871 </SidebarLink>
872 )}
Merge branch 'worktree-agent-a5a5de74d8863d554' into worktree-agent-a16631325aecf58ca873 {shows("keys") && (
874 <SidebarLink to={`${base}/settings/keys`} icon={<KeyRound size={15} />}>
875 Deploy keys
876 </SidebarLink>
877 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look878 {shows("branches") && (
879 <SidebarLink to={`${base}/settings/branches`} icon={<GitBranch size={15} />}>
880 Branches and merging
881 </SidebarLink>
882 )}
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge883 {shows("rules") && (
884 <SidebarLink to={`${base}/settings/rules`} icon={<Scale size={15} />}>
885 Rules
886 </SidebarLink>
887 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look888 {shows("secrets") && (
889 <SidebarLink to={`${base}/settings/secrets`} icon={<Lock size={15} />}>
890 Secrets and variables
891 </SidebarLink>
892 )}
Merge branch 'worktree-agent-a3abfcce648e87dca'893 {shows("actions") && (
894 <SidebarLink to={`${base}/settings/actions`} icon={<PlayCircle size={15} />}>
895 Actions
896 </SidebarLink>
897 )}
898 {shows("environments") && (
899 <SidebarLink to={`${base}/settings/environments`} icon={<Layers size={15} />}>
900 Environments
901 </SidebarLink>
902 )}
Fast pages, required checks on the branch, self-hosted runners, honest incidents903 {shows("runners") && (
904 <SidebarLink to={`${base}/settings/runners`} icon={<ServerCog size={15} />}>
905 Runners
906 </SidebarLink>
907 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look908 {shows("webhooks") && (
909 <SidebarLink to={`${base}/settings/webhooks`} icon={<Webhook size={15} />}>
910 Webhooks
911 </SidebarLink>
912 )}
913 </div>
Project settings move into the sidebar, grouped, with a heading per page914 </nav>
915 );
916}
917
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)918/**
919 * Whether the menus list Settings → Invites (invites to g1t): always while
920 * sign-up takes an invite; once anyone can sign up, only for someone with
921 * invites already made to look back on, which the account menu's data says.
922 */
923function useInvitesListed(): boolean {
924 const inviteOnly = useInviteOnly();
925 const details = useFetcher<AccountMenuData | null>({ key: "account-menu" });
926 useEffect(() => {
927 if (!inviteOnly && details.state === "idle" && details.data === undefined) details.load("/settings/menu.json");
928 // eslint-disable-next-line react-hooks/exhaustive-deps
929 }, [inviteOnly]);
930 return inviteOnly || details.data?.invites_page === true;
931}
932
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas933/** Your own settings, drilled into from Your settings: one page each. */
934function AccountSettingsMenu({ username }: { username: string }) {
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)935 const invites = useInvitesListed();
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas936 const link = (page: AccountSettingsPage, icon: ReactNode) => (
937 <SidebarLink to={`/settings/${page}`} icon={icon}>
938 {ACCOUNT_SETTINGS[page].title}
939 </SidebarLink>
A quicker settings slide: the same curve over 380ms940 );
941 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look942 <nav aria-label="Your settings" className={PANEL}>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas943 <BackRow to="/" label="Your settings" context={username} />
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look944 <div className="mt-2 space-y-px">
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas945 {link("profile", <CircleUserRound size={15} />)}
946 {link("emails", <Mail size={15} />)}
Merge two kinds of invite, kept apart: an invite to g1t (Settings, invite-only only, no workspace unless asked) and an invitation to a workspace (its People page)947 {invites && link("invites", <Ticket size={15} />)}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas948 </div>
949 <Rule />
950 <div className="space-y-px">
951 {link("keys", <Fingerprint size={15} />)}
952 {link("tokens", <KeyRound size={15} />)}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look953 </div>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas954 <Rule />
955 <div className="space-y-px">
Integrations are a directory of connectors, for a workspace and for each person956 {link("integrations", <Blocks size={15} />)}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas957 {link("github", <GithubMark className="size-[15px]" />)}
958 {link("applications", <Plug size={15} />)}
959 </div>
960 <Rule />
961 <div className="space-y-px">
Merge main (membership, two-factor, GitHub repo roles) into tokens962 {link("two-factor", <ShieldCheck size={15} />)}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas963 {link("security-log", <History size={15} />)}
964 </div>
A quicker settings slide: the same curve over 380ms965 </nav>
966 );
967}
968
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put969/**
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.970 * Code's sidebar: its Overview, the projects, what spans them and what is
971 * coming; in a project, drilled into the project's own list, and its
972 * settings one level further in. The address says which, so a link
973 * straight to a project opens the sidebar already drilled in.
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put974 */
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.975function CodeSidebar({
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look976 user,
977 shell,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas978 missing = false,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look979}: {
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.980 user: User;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look981 shell: ShellData;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas982 /** The page is a 404: the address names nothing the viewer can see. */
983 missing?: boolean;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look984}) {
A quicker settings slide: the same curve over 380ms985 const ws = shell.workspace;
986 const { pathname } = useLocation();
987 const going = useNavigation().location?.pathname;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look988 // Where the sidebar is drilled to follows the page being gone to, so it
989 // moves as the link is followed, not once the page arrives.
990 const target = going ?? pathname;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas991 // On a 404, the address is not a place: no list is drilled into from it,
992 // except the project's own when the project is real and visible and only
993 // something inside it is missing (a file, a commit, an issue).
994 const lost = missing && going == null;
A repository has its own sidebar, as settings do995 const active = shell.repo;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look996 // In a repository, or on the way into one, its own list.
A repository has its own sidebar, as settings do997 const repoPath = /^\/([^/]+)\/([^/-][^/]*)(\/|$)/.exec(target);
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.998 const reserved = new Set(["settings", "explore", "search", "new", "u", "pricing", "avatars", "workspaces", "login", "logout", "register", "verify", "forgot", "reset", "device", "oauth", "policies", "security", "support", "status", "invite", "notifications", "inbox", ".well-known"]);
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look999 // An invitation to a repository is answered before its menu means anything.
1000 const inRepo =
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1001 repoPath != null &&
1002 !reserved.has(repoPath[1]) &&
1003 repoPath[2] !== "-" &&
1004 !/^\/[^/]+\/[^/]+\/invitations\/?$/.test(target) &&
1005 (!lost || sameRepo(active, { namespace: repoPath[1]!, name: repoPath[2]! }));
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1006 // A project's settings, one level further in.
Project settings move into the sidebar, grouped, with a heading per page1007 const inRepoSettings = inRepo && REPO_SETTINGS_PAGE.test(target);
Sidebar: no settings flash on the way into a repository, and a better slide1008 // The repository the menu is for: the one loaded if it is the one being
1009 // gone to, else what the address says, at once.
1010 const targetRepo = inRepo && repoPath ? { namespace: repoPath[1], name: repoPath[2] } : null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1011 const guessed: MenuRepo | null = targetRepo
Sidebar: no settings flash on the way into a repository, and a better slide1012 ? sameRepo(active, targetRepo)
1013 ? active
1014 : {
1015 ...targetRepo,
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1016 member: (user.workspaces ?? []).some((m) => m.slug === targetRepo.namespace.toLowerCase()),
Sidebar: no settings flash on the way into a repository, and a better slide1017 }
1018 : null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1019 // The viewer's role there, from the repository's page once it has loaded.
1020 const page = useRouteLoaderData("routes/repo/layout") as
1021 | { repo?: { namespace: string; name: string }; access?: ViewerAccess }
1022 | undefined;
1023 const menuRepo: MenuRepo | null =
1024 guessed && page?.access && page.repo && sameRepo(page.repo, guessed)
1025 ? { ...guessed, member: page.access.insider, settings: seesSettings(page.access), can: page.access.can }
1026 : guessed;
1027
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1028 // The way from Code's list to the one shown.
1029 const trail: Level[] = [{ key: "main", node: ws ? <CodeMenu shell={shell} slug={ws.slug} /> : null }];
1030 if (menuRepo) {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1031 const key = `repo:${menuRepo.namespace}/${menuRepo.name}`.toLowerCase();
1032 // Out of a project: to its workspace's projects when they are yours.
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1033 const home = (user.workspaces ?? []).find((m) => m.slug === menuRepo.namespace.toLowerCase());
1034 const back = home ? { to: `/${home.slug}/-/projects`, label: "All projects" } : { to: ws ? `/${ws.slug}/-/overview` : "/explore", label: "Code" };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1035 trail.push({
1036 key,
1037 node: (
1038 <RepoMenu
1039 repo={menuRepo}
1040 isPrivate={[...shell.repos, ...(shell.shared ?? [])].some((repo) => sameRepo(repo, menuRepo) && repo.isPrivate)}
1041 back={back}
1042 />
1043 ),
1044 });
1045 if (inRepoSettings) trail.push({ key: `${key}:settings`, node: <RepoSettingsMenu repo={menuRepo} /> });
1046 }
1047
A quicker settings slide: the same curve over 380ms1048 return (
1049 <div className="flex h-full flex-col">
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1050 <ModeHeader title="Code" />
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1051 <Drill trail={trail} />
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)1052 </div>
1053 );
1054}
1055
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1056/**
1057 * A mode's sidebar heading: its name, quiet, under the workspace's
1058 * switcher, with what it makes at the end.
1059 */
1060export function ModeHeader({ title, action }: { title: ReactNode; action?: ReactNode }) {
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)1061 return (
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1062 <div className="flex h-9 shrink-0 items-center gap-1 pr-1 pl-3">
1063 <h2 className="min-w-0 grow truncate text-xs font-medium text-faint">{title}</h2>
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)1064 {action}
1065 </div>
1066 );
1067}
1068
1069/**
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1070 * Code's own list (beside the dock): only code. Its Overview (Mission
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)1071 * control's code panels), the projects, what spans them, and what is
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1072 * coming. The workspace's people, money and settings are elsewhere;
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)1073 * agents, context and memory are Agents'.
1074 */
1075function CodeMenu({ shell, slug }: { shell: ShellData; slug: string }) {
1076 const { pathname } = useLocation();
1077 const going = useNavigation().location?.pathname;
1078 const path = going ?? pathname;
1079 const at = (page: string) => path === `/${slug}/-/${page}` || path.startsWith(`/${slug}/-/${page}/`);
1080 const shared = shell.shared ?? [];
1081 return (
1082 <nav aria-label="Code" className={PANEL}>
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1083 <div className="space-y-px">
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)1084 <SidebarLink to={`/${slug}/-/overview`} icon={<LayoutDashboard size={15} />} current={at("overview")}>
1085 Overview
1086 </SidebarLink>
1087 </div>
1088 <div className="mt-3">
1089 <SidebarProjects slug={slug} shell={shell} current={at("projects")} />
1090 </div>
1091 <Rule />
1092 <div className="space-y-px">
1093 <SidebarLink to={`/${slug}/-/security`} icon={<ShieldCheck size={15} />} current={at("security") && !at("security/settings")}>
1094 Security
1095 </SidebarLink>
1096 <SidebarLink to={`/${slug}/-/packages`} icon={<Package size={15} />} current={at("packages")}>
1097 Packages
1098 </SidebarLink>
1099 {INSIGHTS && (
1100 <SidebarSoonLink to={`/${slug}/-/insights`} icon={<TrendingUp size={15} />} about={INSIGHTS.summary} current={at("insights")}>
1101 {INSIGHTS.title}
1102 </SidebarSoonLink>
1103 )}
1104 {roadmapIn("Workspace")
1105 .filter((item) => item.key !== "insights" && item.key !== "teams" && item.key !== "fleet")
1106 .map((item) => (
1107 <SidebarSoonLink key={item.key} to={`/${slug}/-/soon/${item.key}`} icon={WORKSPACE_ICONS[item.key] ?? <Sparkles size={15} />} about={item.summary}>
1108 {item.title === "Board" ? "Boards" : item.title}
1109 </SidebarSoonLink>
1110 ))}
1111 </div>
1112 {shared.length > 0 && (
1113 <>
1114 <Rule />
1115 <SidebarGroup title="Shared with you">
1116 {shared.map((repo) => (
1117 <SidebarLink
1118 key={`${repo.namespace}/${repo.name}`}
1119 to={`/${repo.namespace}/${repo.name}`}
1120 icon={repo.isPrivate ? <Lock size={15} /> : <Box size={15} />}
1121 drill="hover"
1122 >
1123 <span className="font-mono text-faint">{repo.namespace}/</span>
1124 {repo.name}
1125 </SidebarLink>
1126 ))}
1127 </SidebarGroup>
1128 </>
1129 )}
1130 </nav>
1131 );
1132}
1133
1134/** Workspace pages that sit in its Settings list, drilled into from the Workspace sidebar. */
1135const WORKSPACE_SETTINGS = ["settings", "repositories", "tokens", "personal-access-tokens", "secrets", "actions", "runners", "webhooks", "emoji"];
1136
1137/**
1138 * The Workspace mode's sidebar: the workspace itself, for every member.
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1139 * Its overview, money, connections, policies and record, then its
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)1140 * settings as a list of their own. Owner-only pages stay owner-only.
1141 */
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1142export function WorkspaceSidebar({ slug, owner }: { slug: string; owner: boolean }) {
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)1143 const { pathname } = useLocation();
1144 const going = useNavigation().location?.pathname;
1145 const path = going ?? pathname;
1146 const page = path.startsWith(`/${slug}/-/`) ? path.slice(`/${slug}/-/`.length) : "";
1147 const top = page.split("/")[0] ?? "";
1148 const at = (...pages: string[]) => pages.some((p) => page === p || page.startsWith(`${p}/`));
1149 const inSettings = WORKSPACE_SETTINGS.includes(top);
1150 const main = (
1151 <nav aria-label="Workspace" className={PANEL}>
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1152 <div className="space-y-px">
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)1153 <SidebarLink to={`/${slug}/-/workspace`} icon={<LayoutGrid size={15} />} current={at("workspace")}>
1154 Overview
1155 </SidebarLink>
1156 </div>
1157 <SidebarGroup title="Usage and billing" className="mt-3">
1158 <SidebarLink to={`/${slug}/-/usage`} icon={<BarChart3 size={15} />} current={at("usage", "gateway")}>
1159 Usage
1160 </SidebarLink>
1161 <SidebarLink to={`/${slug}/-/billing`} icon={<CreditCard size={15} />} current={at("billing")}>
1162 Billing and plans
1163 </SidebarLink>
1164 </SidebarGroup>
1165 <SidebarGroup title="Connections" className="mt-3">
1166 <SidebarLink to={`/${slug}/-/integrations`} icon={<Plug size={15} />} current={at("integrations")}>
1167 Integrations
1168 </SidebarLink>
1169 </SidebarGroup>
1170 <SidebarGroup title="Security policies" className="mt-3">
1171 <SidebarLink to={`/${slug}/-/security/settings`} icon={<ShieldCheck size={15} />} current={at("security/settings")}>
1172 Security settings
1173 </SidebarLink>
1174 <SidebarLink to={`/${slug}/-/guardrails`} icon={<Gauge size={15} />} current={at("guardrails")}>
1175 Guardrails
1176 </SidebarLink>
1177 <SidebarLink to={`/${slug}/-/rules`} icon={<Scale size={15} />} current={at("rules")}>
1178 Rules
1179 </SidebarLink>
1180 </SidebarGroup>
1181 <Rule />
1182 <div className="space-y-px">
1183 <SidebarLink to={`/${slug}/-/audit`} icon={<History size={15} />} current={at("audit")}>
1184 Audit log
1185 </SidebarLink>
1186 <SidebarLink to={owner ? `/${slug}/-/settings` : `/${slug}/-/repositories`} icon={<Settings size={15} />} drill current={inSettings}>
1187 Settings
1188 </SidebarLink>
1189 </div>
1190 </nav>
1191 );
1192 const settings = (
1193 <nav aria-label="Workspace settings" className={PANEL}>
1194 <BackRow to={`/${slug}/-/workspace`} label="Settings" context={slug} />
1195 <div className="mt-2 space-y-px">
1196 {owner && (
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1197 <SidebarLink to={`/${slug}/-/settings`} icon={<Settings size={15} />} end>
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)1198 General
1199 </SidebarLink>
1200 )}
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1201 <SidebarLink to={`/${slug}/-/settings/chat`} icon={<MessagesSquare size={15} />}>
1202 Chat
1203 </SidebarLink>
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)1204 <SidebarLink to={`/${slug}/-/repositories`} icon={<BookMarked size={15} />}>
1205 Repositories
1206 </SidebarLink>
1207 <SidebarLink to={`/${slug}/-/tokens`} icon={<KeyRound size={15} />}>
1208 Access tokens
1209 </SidebarLink>
1210 {owner && (
1211 <SidebarLink to={`/${slug}/-/personal-access-tokens`} icon={<UserRoundKey size={15} />}>
1212 Personal access tokens
1213 </SidebarLink>
1214 )}
1215 <SidebarLink to={`/${slug}/-/webhooks`} icon={<Webhook size={15} />}>
1216 Webhooks
1217 </SidebarLink>
1218 <SidebarLink to={`/${slug}/-/emoji`} icon={<Smile size={15} />}>
1219 Emoji
1220 </SidebarLink>
1221 </div>
1222 <SidebarGroup title="Runs" className="mt-3">
1223 <SidebarLink to={`/${slug}/-/secrets`} icon={<Lock size={15} />}>
1224 Secrets and variables
1225 </SidebarLink>
1226 <SidebarLink to={`/${slug}/-/actions`} icon={<PlayCircle size={15} />}>
1227 Actions
1228 </SidebarLink>
1229 {owner && (
1230 <SidebarLink to={`/${slug}/-/runners`} icon={<ServerCog size={15} />}>
1231 Runners
1232 </SidebarLink>
1233 )}
1234 </SidebarGroup>
1235 </nav>
1236 );
1237 const trail: Level[] = [{ key: "workspace", node: main }];
1238 if (inSettings) trail.push({ key: "workspace:settings", node: settings });
1239 return (
1240 <div className="flex h-full flex-col">
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1241 <ModeHeader title="Workspace" />
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)1242 <Drill trail={trail} />
1243 </div>
1244 );
1245}
1246
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1247/** People's sidebar: everyone in the workspace, and its teams. */
1248function PeopleSidebar({ slug }: { slug: string }) {
1249 const { pathname } = useLocation();
1250 const going = useNavigation().location?.pathname;
1251 const path = going ?? pathname;
1252 const at = (page: string) => path === `/${slug}/-/${page}` || path.startsWith(`/${slug}/-/${page}/`);
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)1253 return (
1254 <div className="flex h-full flex-col">
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1255 <ModeHeader title="People" />
1256 <nav aria-label="People" className={PANEL}>
1257 <div className="space-y-px">
1258 <SidebarLink to={`/${slug}/-/people`} icon={<Users size={15} />} current={at("people")}>
1259 Everyone
1260 </SidebarLink>
1261 <SidebarLink to={`/${slug}/-/teams`} icon={<UsersRound size={15} />} current={at("teams")}>
1262 Teams
1263 </SidebarLink>
1264 </div>
1265 </nav>
1266 </div>
1267 );
1268}
1269
1270/**
1271 * Notifications' sidebar: what you have not finished with, what you saved
1272 * and what is done; then why you were told, which narrows any of them.
1273 */
1274function NotificationsSidebar({ counts }: { counts: InboxCounts | null }) {
1275 const { search } = useLocation();
1276 const params = new URLSearchParams(search);
1277 const view = inboxView(params.get("view"));
1278 const reason = inboxReason(params.get("reason"));
1279 const tab = params.get("tab");
1280 const address = (changes: Record<string, string | null>) => {
1281 const merged: Record<string, string | null> = { tab, view: view === "inbox" ? null : view, reason, ...changes };
1282 const next = new URLSearchParams();
1283 for (const [name, value] of Object.entries(merged)) if (value) next.set(name, value);
1284 const query = next.toString();
1285 return query ? `/notifications?${query}` : "/notifications";
1286 };
1287 const views = [
1288 { view: "inbox", label: "Everything", icon: <Bell size={15} />, count: counts?.unread },
1289 { view: "saved", label: "Saved", icon: <Bookmark size={15} /> },
1290 { view: "done", label: "Done", icon: <Check size={15} /> },
1291 ] as const;
1292 return (
1293 <div className="flex h-full flex-col">
1294 <ModeHeader title="Notifications" />
1295 <nav aria-label="Notifications" className={PANEL}>
1296 <div className="space-y-px">
1297 {views.map((entry) => (
1298 <SidebarLink
1299 key={entry.view}
1300 to={address({ view: entry.view === "inbox" ? null : entry.view, before: null })}
1301 icon={entry.icon}
1302 count={"count" in entry ? (entry.count ?? undefined) : undefined}
1303 current={view === entry.view}
1304 >
1305 {entry.label}
1306 </SidebarLink>
1307 ))}
1308 </div>
1309 <SidebarGroup title="Why you were told" className="mt-4">
1310 {REASON_FILTERS.map((entry) => (
1311 <SidebarLink
1312 key={entry.reason ?? "any"}
1313 to={address({ reason: entry.reason, before: null })}
1314 icon={<span className="block size-[15px]" />}
1315 current={reason === entry.reason}
1316 >
1317 {entry.reason == null ? "Any reason" : entry.label}
1318 </SidebarLink>
1319 ))}
1320 </SidebarGroup>
1321 </nav>
1322 </div>
1323 );
1324}
1325
1326/** Your own settings, beside the page: under the account menu, not any workspace's. */
1327export function AccountSidebar({ username }: { username: string }) {
1328 return (
1329 <div className="flex h-full flex-col">
1330 <ModeHeader title="Your account" />
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)1331 <div className="min-h-0 grow">
1332 <AccountSettingsMenu username={username} />
A quicker settings slide: the same curve over 380ms1333 </div>
1334 </div>
1335 );
1336}
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)1337
A quicker settings slide: the same curve over 380ms1338/** Words for the sections a path can end in. */
1339const SECTIONS: Record<string, string> = {
1340 issues: "Issues",
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1341 milestones: "Milestones",
1342 labels: "Labels",
A quicker settings slide: the same curve over 380ms1343 pulls: "Pull requests",
1344 queue: "Merge queue",
1345 commits: "Commits",
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales1346 plans: "Outcomes",
1347 actions: "Workflows",
1348 soon: "Soon",
Deployments: a preview for every pull request, production on g1t.page1349 deployments: "Deployments",
Projects: what a workspace builds and runs, first on every page1350 repository: "Repository",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1351 access: "Access",
1352 invitations: "Invitation",
1353 repositories: "Repositories",
Branches and Tags pages, each file's last commit, and the branch menu on files1354 branches: "Branches",
1355 tags: "Tags",
Compare: any two branches, the commits one has that the other does not, and the diff, with Open a pull request1356 compare: "Compare",
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales1357 code: "Files",
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs1358 secrets: "Secrets and variables",
A quicker settings slide: the same curve over 380ms1359 settings: "Settings",
Navigation: the workspace's own page with tabs, pins and recent in the sidebar1360 people: "People",
1361 projects: "Projects",
1362 teams: "Teams",
A quicker settings slide: the same curve over 380ms1363 tokens: "Access tokens",
Settings: fine-grained tokens, workspace token Admin, workspace personal access token rules1364 "personal-access-tokens": "Personal access tokens",
A quicker settings slide: the same curve over 380ms1365 usage: "Usage",
Site: the AI Gateway page's breadcrumb reads "AI Gateway"1366 gateway: "AI Gateway",
Secrets and variables: one list, rows per environment, for workflows and deployments1367 billing: "Billing and plans",
A quicker settings slide: the same curve over 380ms1368 integrations: "Integrations",
Webhooks: every event, to your own addresses, signed and retried1369 webhooks: "Webhooks",
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)1370 emoji: "Emoji",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1371 domains: "Domains",
1372 guardrails: "Guardrails",
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge1373 rules: "Rules",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1374 audit: "Audit log",
Files pages say Files in the trail and keep the description in About only1375 tree: "Files",
1376 blob: "Files",
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail1377 agents: "Agents",
1378 context: "Context",
1379 memory: "Memory",
1380 security: "Security",
1381 packages: "Packages",
1382 runners: "Runners",
Merge branch 'worktree-agent-a3abfcce648e87dca'1383 environments: "Environments",
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail1384 workflows: "Workflows",
1385 observability: "Observability",
1386 insights: "Insights",
1387 sessions: "Sessions",
Chat and workspace agents: channels, DMs and named agents you talk to1388 chat: "Chat",
Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash.1389 artifacts: "Artifacts",
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1390 today: "Today",
1391 apps: "Apps",
Chat and workspace agents: channels, DMs and named agents you talk to1392 "code-access": "Code access",
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)1393 overview: "Overview",
1394 workspace: "Workspace",
A quicker settings slide: the same curve over 380ms1395};
1396
Merge branch 'worktree-agent-a3abfcce648e87dca'1397/** Settings pages whose name differs from the section's of the same word. */
1398const SETTINGS_SECTIONS: Record<string, string> = { branches: "Branches and merging", actions: "Actions" };
1399
A quicker settings slide: the same curve over 380ms1400/** Where the page is, as a trail of links: workspace / repository / section. */
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1401function Breadcrumbs({
1402 pathname,
1403 missing,
1404 repo,
1405 workspace,
1406}: {
1407 pathname: string;
1408 missing?: boolean;
1409 repo?: ShellData["repo"];
1410 /** The workspace you are in: the switcher names it, so the trail starts after it. */
1411 workspace: string | null;
1412}) {
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1413 // A 404 names nothing from the address, unless the project is real and
1414 // visible and only something inside it is missing.
1415 const visibleRepo = /^\/([^/]+)\/([^/-][^/]*)(\/|$)/.exec(pathname);
1416 if (missing && !(visibleRepo && sameRepo(repo ?? null, { namespace: visibleRepo[1]!, name: visibleRepo[2]! }))) {
1417 return <span className="text-sm font-medium">Not found</span>;
1418 }
A quicker settings slide: the same curve over 380ms1419 const parts = pathname.split("/").filter(Boolean);
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1420 const reserved = ["settings", "explore", "new", "search", "workspaces", "policies", "security", "support", "status", "invite", "notifications"];
1421 if (parts.length === 0) return <span className="text-sm font-medium">Today</span>;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1422 // Your settings: Settings / Emails.
1423 if (parts[0] === "settings") {
1424 const page = accountSettingsPage(pathname);
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1425 return <Trail trail={[{ label: "Settings", to: FIRST_SETTINGS_PAGE }, ...(page ? [{ label: ACCOUNT_SETTINGS[page].title, to: `/settings/${page}` }] : [])]} />;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1426 }
A quicker settings slide: the same curve over 380ms1427 if (reserved.includes(parts[0]!)) {
1428 const words: Record<string, string> = {
1429 settings: "Account",
1430 explore: "Explore",
Projects live: fixes from walking them end to end1431 new: "New project",
A quicker settings slide: the same curve over 380ms1432 search: "Search",
1433 workspaces: "New workspace",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1434 policies: "Policies",
1435 security: "Security",
1436 support: "Support",
1437 status: "Status",
1438 invite: "Invite",
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1439 notifications: "Notifications",
A quicker settings slide: the same curve over 380ms1440 };
1441 return <span className="text-sm font-medium">{words[parts[0]!]}</span>;
1442 }
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put1443 // A person's profile, by their handle.
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1444 if (parts[0] === "u" && parts[1]) return <ProfileCrumb username={parts[1]} />;
A quicker settings slide: the same curve over 380ms1445 const [owner, second, third, fourth] = parts;
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1446 const ours = workspace != null && owner!.toLowerCase() === workspace.toLowerCase();
1447 const trail: Crumb[] = ours ? [] : [{ label: owner!, to: `/${owner}`, mono: true }];
A quicker settings slide: the same curve over 380ms1448 if (second === "-") {
1449 const page = `/${owner}/-/${third}`;
1450 if (third && SETTINGS_PAGE.test(page)) {
1451 trail.push({ label: "Settings", to: `/${owner}/-/settings` });
1452 trail.push({ label: third === "settings" ? "General" : (SECTIONS[third] ?? third), to: page });
1453 } else if (third) trail.push({ label: SECTIONS[third] ?? third, to: page });
1454 } else if (second) {
1455 const repo = `/${owner}/${second}`;
1456 trail.push({ label: second, to: repo, mono: true });
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1457 if (third === "pull" && fourth) trail.push({ label: `Pull request #${fourth}`, short: `#${fourth}`, to: `${repo}/pull/${fourth}` });
1458 else if (third === "issues" && fourth && fourth !== "new") trail.push({ label: `Issue #${fourth}`, short: `#${fourth}`, to: `${repo}/issues/${fourth}` });
A quicker settings slide: the same curve over 380ms1459 else if (third === "commit" && fourth) trail.push({ label: fourth.slice(0, 7), to: `${repo}/commit/${fourth}`, mono: true });
Secrets and variables: one list, rows per environment, for workflows and deployments1460 else if (third && SECTIONS[third]) {
1461 trail.push({ label: SECTIONS[third]!, to: `${repo}/${third}` });
1462 // A settings page names which one: Settings / Secrets and variables.
1463 if (third === "settings" && fourth && SECTIONS[fourth]) {
Merge branch 'worktree-agent-a3abfcce648e87dca'1464 trail.push({ label: SETTINGS_SECTIONS[fourth] ?? SECTIONS[fourth]!, to: `${repo}/settings/${fourth}` });
Secrets and variables: one list, rows per environment, for workflows and deployments1465 }
1466 }
A quicker settings slide: the same curve over 380ms1467 }
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1468 if (trail.length === 0) trail.push({ label: "Overview", to: `/${owner}` });
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1469 return <Trail trail={trail} />;
1470}
1471
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1472/** A profile's place in the top bar: the person's avatar and @handle, from the page once it has loaded. */
1473function ProfileCrumb({ username }: { username: string }) {
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers1474 const page = useRouteLoaderData("routes/user") as { profile?: { username: string; displayUsername?: string | null; avatar: string | null } } | undefined;
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1475 const profile = page?.profile?.username.toLowerCase() === username.toLowerCase() ? page.profile : null;
1476 return (
1477 <Link to={`/u/${profile?.username ?? username}`} aria-current="page" className="flex min-w-0 items-center gap-2 rounded px-1 py-0.5 transition-colors hover:bg-raised">
1478 <Avatar name={profile?.username ?? username} image={profile?.avatar ?? null} size={20} />
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers1479 <span className="truncate font-mono text-[0.8125rem] font-medium">@{profile ? shownUsername(profile) : username}</span>
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1480 </Link>
1481 );
1482}
1483
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1484/** One link of the trail; `short` is what a phone shows when it is the page itself. */
1485type Crumb = { label: string; to: string; mono?: boolean; short?: string };
1486
1487/**
1488 * The trail of links. On a phone there is room for one: the page itself,
1489 * with a way back to where it sits; the whole trail from a wider screen up.
1490 */
1491function Trail({ trail }: { trail: Crumb[] }) {
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)1492 // Up on a phone, unless up is the workspace itself: its pages are the tabs.
1493 const up = trail.length > 1 && !/^\/[^/]+$/.test(trail[trail.length - 2]!.to) ? trail[trail.length - 2]! : null;
A quicker settings slide: the same curve over 380ms1494 return (
1495 <nav aria-label="Where you are" className="flex min-w-0 items-center gap-1.5 text-sm">
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1496 {up && (
1497 <Link
1498 to={up.to}
1499 prefetch="intent"
1500 aria-label={`Back to ${up.label}`}
1501 className="-ml-1 flex size-8 shrink-0 items-center justify-center rounded-md text-muted transition-colors hover:bg-raised hover:text-fg sm:hidden"
1502 >
1503 <ChevronLeft size={16} />
1504 </Link>
1505 )}
1506 {trail.map((crumb, index) => {
1507 const last = index === trail.length - 1;
1508 return (
1509 <span key={index} className={`min-w-0 items-center gap-1.5 ${last ? "flex" : "hidden sm:flex"}`}>
1510 {index > 0 && <span className="hidden text-line-strong sm:inline">/</span>}
1511 <Link
1512 to={crumb.to}
1513 prefetch="intent"
1514 aria-current={last ? "page" : undefined}
1515 className={`truncate rounded px-1 py-0.5 transition-colors hover:bg-raised ${
1516 last ? "font-medium text-fg" : "text-muted hover:text-fg"
1517 } ${crumb.mono ? "font-mono text-[0.8125rem]" : ""}`}
1518 >
1519 {last && crumb.short ? (
1520 <>
1521 <span className="sm:hidden">{crumb.short}</span>
1522 <span className="hidden sm:inline">{crumb.label}</span>
1523 </>
1524 ) : (
1525 crumb.label
1526 )}
1527 </Link>
1528 </span>
1529 );
1530 })}
A quicker settings slide: the same curve over 380ms1531 </nav>
1532 );
1533}
1534
Search across all of g1t, Explore, and a command palette1535type Command = PaletteCommand;
A quicker settings slide: the same curve over 380ms1536
1537/** Everything the palette can jump to, from what the sidebar already knows. */
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1538function commandsFor(user: User, shell: ShellData): Command[] {
1539 const ws = shell.workspace;
A quicker settings slide: the same curve over 380ms1540 const commands: Command[] = [
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1541 ...(ws
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)1542 ? [
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1543 { label: "Today", to: todayPath(ws.slug), icon: <Sun size={15} /> },
1544 { label: "Chat", to: `/${ws.slug}/-/chat`, icon: <MessagesSquare size={15} /> },
1545 { label: "Agents", to: `/${ws.slug}/-/agents`, icon: <Sparkles size={15} /> },
1546 ...(hasCodeAccess(ws) ? [{ label: "Code overview", to: `/${ws.slug}/-/overview`, icon: <Code2 size={15} /> }] : []),
1547 { label: "Artifacts", to: `/${ws.slug}/-/artifacts`, icon: <Shapes size={15} /> },
1548 { label: "Apps", hint: "Everything installed that you can use", to: `/${ws.slug}/-/apps`, icon: <LayoutGrid size={15} /> },
1549 { label: "Workspace", hint: "Billing, policies, settings", to: `/${ws.slug}/-/workspace`, icon: <Building2 size={15} /> },
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)1550 ]
1551 : []),
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step1552 ...(shell.repos.length > 0
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent1553 ? [{ label: "Put an agent on it", hint: "Open an issue and assign g1t", to: "/?agent=new", icon: <Sparkles size={15} /> }]
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step1554 : []),
A quicker settings slide: the same curve over 380ms1555 { label: "Explore repositories", to: "/explore", icon: <Compass size={15} /> },
Search across all of g1t, Explore, and a command palette1556 { label: "Search g1t", hint: "Repositories, code, issues, people", to: "/search", icon: <Search size={15} /> },
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1557 { label: "Notifications", hint: "What needs you", to: "/notifications", icon: <Bell size={15} /> },
Projects: what a workspace builds and runs, first on every page1558 { label: "New project", to: "/new", icon: <Plus size={15} /> },
A quicker settings slide: the same curve over 380ms1559 { label: "New workspace", to: "/workspaces/new", icon: <Plus size={15} /> },
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1560 { label: "Your settings", to: FIRST_SETTINGS_PAGE, icon: <Settings size={15} /> },
1561 ...(Object.keys(ACCOUNT_SETTINGS) as AccountSettingsPage[])
1562 .filter((page) => page !== "profile")
1563 .map((page) => ({ label: ACCOUNT_SETTINGS[page].title, hint: "Your settings", to: `/settings/${page}`, icon: <Settings size={15} /> })),
A quicker settings slide: the same curve over 380ms1564 ];
1565 const repo = shell.repo;
1566 if (repo) {
1567 const base = `/${repo.namespace}/${repo.name}`;
1568 const name = `${repo.namespace}/${repo.name}`;
1569 commands.unshift(
Projects: what a workspace builds and runs, first on every page1570 { label: "Overview", hint: name, to: base, icon: <LayoutGrid size={15} /> },
1571 { label: "Code", hint: name, to: `${base}/code`, icon: <Code2 size={15} /> },
A quicker settings slide: the same curve over 380ms1572 { label: "Issues", hint: name, to: `${base}/issues`, icon: <CircleDot size={15} /> },
1573 { label: "New issue", hint: name, to: `${base}/issues/new`, icon: <Plus size={15} /> },
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step1574 ...(repo.member
1575 ? [{ label: `Put an agent on ${repo.name}`, hint: name, to: `${base}/issues/new?agent=1`, icon: <Sparkles size={15} /> }]
1576 : []),
A quicker settings slide: the same curve over 380ms1577 { label: "Pull requests", hint: name, to: `${base}/pulls`, icon: <GitPullRequest size={15} /> },
1578 { label: "Commits", hint: name, to: `${base}/commits`, icon: <History size={15} /> },
1579 ...(repo.member
1580 ? [
1581 { label: "Plan work", hint: name, to: `${base}/plans`, icon: <ListTree size={15} /> },
Projects: what a workspace builds and runs, first on every page1582 { label: "Deployments", hint: name, to: `${base}/deployments`, icon: <Rocket size={15} /> },
1583 { label: "Secrets and variables", hint: name, to: `${base}/settings/secrets`, icon: <Lock size={15} /> },
1584 { label: "Project settings", hint: name, to: `${base}/settings`, icon: <Settings size={15} /> },
1585 { label: "Repository settings", hint: name, to: `${base}/settings/repository`, icon: <Settings size={15} /> },
A quicker settings slide: the same curve over 380ms1586 ]
1587 : []),
1588 );
1589 }
1590 for (const membership of user.workspaces ?? []) {
1591 commands.push(
Workspace names and icons, and a component kit for every control1592 { label: displayName(membership), hint: `Workspace · ${membership.slug}`, to: `/${membership.slug}`, icon: <Avatar name={membership.slug} image={membership.avatar} size={15} square /> },
Navigation: the workspace's own page with tabs, pins and recent in the sidebar1593 { label: "All projects", hint: membership.slug, to: `/${membership.slug}/-/projects`, icon: <LayoutGrid size={15} /> },
1594 { label: "People", hint: membership.slug, to: `/${membership.slug}/-/people`, icon: <Users size={15} /> },
A quicker settings slide: the same curve over 380ms1595 { label: "Usage", hint: membership.slug, to: `/${membership.slug}/-/usage`, icon: <BarChart3 size={15} /> },
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens1596 { label: "AI Gateway", hint: `${membership.slug} · Usage`, to: `/${membership.slug}/-/gateway`, icon: <Network size={15} /> },
Projects: what a workspace builds and runs, first on every page1597 { label: "Billing and plans", hint: `${membership.slug} · Settings`, to: `/${membership.slug}/-/billing`, icon: <CreditCard size={15} /> },
A quicker settings slide: the same curve over 380ms1598 { label: "Access tokens", hint: `${membership.slug} · Settings`, to: `/${membership.slug}/-/tokens`, icon: <KeyRound size={15} /> },
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1599 { label: "Integrations", hint: membership.slug, to: `/${membership.slug}/-/integrations`, icon: <Plug size={15} /> },
A quicker settings slide: the same curve over 380ms1600 );
1601 }
1602 for (const listed of shell.repos) {
1603 commands.push({
Projects: what a workspace builds and runs, first on every page1604 label: listed.title ?? listed.name,
1605 hint: `${listed.namespace} · Project`,
A quicker settings slide: the same curve over 380ms1606 to: `/${listed.namespace}/${listed.name}`,
Projects: what a workspace builds and runs, first on every page1607 icon: <Box size={15} />,
A quicker settings slide: the same curve over 380ms1608 });
1609 }
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step1610 // "Put an agent on …": one per project, after the projects themselves.
1611 for (const listed of shell.repos) {
1612 if (repo && listed.namespace === repo.namespace && listed.name === repo.name) continue;
1613 commands.push({
1614 label: `Put an agent on ${listed.title ?? listed.name}`,
1615 hint: `${listed.namespace}/${listed.name}`,
1616 to: `/${listed.namespace}/${listed.name}/issues/new?agent=1`,
1617 icon: <Sparkles size={15} />,
1618 });
1619 }
A quicker settings slide: the same curve over 380ms1620 return commands;
1621}
1622
1623/**
Merge branch 'worktree-agent-aca4790ea223aa235'1624 * The page while the next one loads: after a moment it dims, under the
1625 * bar below, so it is plainly on its way out rather than frozen, and the
1626 * next page fades up from there. Sending a form does not dim it: the
1627 * form's button says it is working. Spread on the element holding the page.
1628 */
1629export function useLeaving() {
1630 const navigation = useNavigation();
1631 const method = navigation.formMethod?.toUpperCase();
1632 const leaving = navigation.state === "loading" && (method == null || method === "GET");
1633 return {
1634 "aria-busy": leaving || undefined,
1635 className: `transition-opacity motion-reduce:transition-none ${leaving ? "opacity-60 delay-200 duration-300" : "duration-150"}`,
1636 };
1637}
1638
1639/**
A quicker settings slide: the same curve over 380ms1640 * A bar across the top of the page while the next one loads, as GitHub
1641 * has: it appears at once, creeps towards the end while waiting, then fills
1642 * and fades when the page arrives.
1643 */
1644export function Progress() {
1645 const navigation = useNavigation();
1646 const busy = navigation.state !== "idle";
1647 const [width, setWidth] = useState(0);
1648 const [visible, setVisible] = useState(false);
1649 useEffect(() => {
1650 if (busy) {
1651 setVisible(true);
1652 setWidth(12);
1653 // Slows as it goes, never quite arriving until the page does.
1654 const timer = setInterval(() => setWidth((now) => now + (90 - now) * 0.12), 200);
1655 return () => clearInterval(timer);
1656 }
1657 setWidth((now) => (now > 0 ? 100 : 0));
1658 const fade = setTimeout(() => setVisible(false), 250);
1659 const reset = setTimeout(() => setWidth(0), 550);
1660 return () => {
1661 clearTimeout(fade);
1662 clearTimeout(reset);
1663 };
1664 }, [busy]);
1665 return (
1666 <div
1667 aria-hidden="true"
1668 className={`pointer-events-none fixed inset-x-0 top-0 z-[60] h-[3px] transition-opacity duration-300 ${
1669 visible ? "opacity-100" : "opacity-0"
1670 }`}
1671 >
1672 <div
1673 className="h-full bg-accent shadow-[0_0_10px_var(--color-accent)] transition-[width] duration-200 ease-out"
1674 style={{ width: `${width}%` }}
1675 />
1676 </div>
1677 );
1678}
1679
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)1680/** The top bar's way to g1t: the direct message with the workspace's orchestrator, opened or made. */
1681function AskG1tButton({ slug }: { slug: string }) {
1682 return (
1683 <Hint label="Ask g1t">
1684 <Link
1685 to={`/${slug}/-/chat?agent=g1t`}
1686 aria-label="Ask g1t"
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1687 className="flex h-8 items-center gap-1.5 rounded-md border border-line px-1.5 text-sm text-fg/90 transition-colors hover:border-line-strong hover:bg-raised hover:text-fg sm:px-2.5"
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)1688 >
1689 <G1tMark size={18} />
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1690 <span className="hidden lg:inline">Ask g1t</span>
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)1691 </Link>
1692 </Hint>
1693 );
1694}
1695
A quicker settings slide: the same curve over 380ms1696/**
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1697 * Which sidebar sits beside the page: each mode's own, or none. Today and
1698 * Apps are pages at full width, and so are g1t's public pages, such as a
1699 * profile, which are no workspace's. Without a workspace, only your own
1700 * settings and Notifications have one.
Chat and workspace agents: channels, DMs and named agents you talk to1701 */
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1702function sidebarFor(mode: ModeKey, workspace: boolean): Panel | null {
1703 if (!workspace) return mode === "account" || mode === "notifications" ? mode : null;
1704 if (mode === "today" || mode === "apps" || mode === "site") return null;
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)1705 return mode;
Chat and workspace agents: channels, DMs and named agents you talk to1706}
1707
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1708/** The sidebars that sit beside the page, one per mode that has one. */
1709type Panel = "chat" | "artifacts" | "agents" | "code" | "notifications" | "people" | "workspace" | "account";
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)1710
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1711/** Each sidebar's name, for the button that opens it on a phone. */
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 bar1712const MODE_MENU: Record<Panel, string> = {
1713 chat: "Chat",
Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash.1714 artifacts: "Artifacts",
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 bar1715 agents: "Agents",
1716 code: "Code",
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1717 notifications: "Notifications",
1718 people: "People",
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 bar1719 workspace: "Workspace",
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1720 account: "Your account",
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 bar1721};
1722
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1723/** Whether a key press happened in something you type into, where Ctrl B is the editor's. */
1724function typing(target: EventTarget | null): boolean {
1725 if (!(target instanceof HTMLElement)) return false;
1726 return target.isContentEditable || target.closest("input, textarea, select, [contenteditable=''], [contenteditable='true'], [role='textbox']") != null;
1727}
1728
1729/** Ctrl B (⌘B on a Mac) shows or hides the sidebar, except while typing. */
1730function useSidebarShortcut(toggle: () => void) {
1731 useEffect(() => {
1732 const onKey = (event: KeyboardEvent) => {
1733 if (event.key.toLowerCase() !== "b" || event.altKey || event.shiftKey || !(event.ctrlKey || event.metaKey)) return;
1734 if (event.defaultPrevented || typing(event.target)) return;
1735 event.preventDefault();
1736 toggle();
1737 };
1738 window.addEventListener("keydown", onKey);
1739 return () => window.removeEventListener("keydown", onKey);
1740 }, [toggle]);
1741}
1742
1743/** The button that shows or hides the sidebar. */
1744function SidebarToggle({ onClick, open, className = "" }: { onClick: () => void; open: boolean; className?: string }) {
1745 const key = sidebarKeyLabel(typeof navigator === "undefined" ? null : navigator.platform);
1746 return (
1747 <Hint label={`Toggle sidebar (${key})`}>
1748 <button
1749 type="button"
1750 aria-label={open ? "Hide the sidebar" : "Show the sidebar"}
1751 aria-expanded={open}
1752 onClick={onClick}
1753 className={`flex size-8 shrink-0 items-center justify-center rounded-md text-muted outline-none transition-colors hover:bg-raised hover:text-fg focus-visible:ring-2 focus-visible:ring-accent ${className}`}
1754 >
1755 <PanelLeft size={17} />
1756 </button>
1757 </Hint>
1758 );
1759}
1760
Chat and workspace agents: channels, DMs and named agents you talk to1761/**
The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.1762 * The app: three surfaces that never blur
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1763 * together. The dock, a floating bar of apps down the left; the mode's
1764 * sidebar, flat on the background beside it, which folds away with Ctrl B
1765 * and is a drawer below 1024px; and the page, a rounded panel inset from
1766 * the window, with its header across the top: the sidebar's toggle, where
1767 * you are, search, Ask g1t and Create new. On a phone the dock is a bar
1768 * along the bottom. Only for someone signed in; without a workspace yet,
1769 * there is no dock.
A quicker settings slide: the same curve over 380ms1770 */
1771export function AppShell({
1772 user,
1773 shell,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1774 missing = false,
A quicker settings slide: the same curve over 380ms1775 banner,
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1776 sidebarClosed = false,
A quicker settings slide: the same curve over 380ms1777 children,
1778}: {
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1779 user: User;
A quicker settings slide: the same curve over 380ms1780 shell: ShellData;
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1781 /** The page is a 404 (see CodeSidebar). */
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1782 missing?: boolean;
A quicker settings slide: the same curve over 380ms1783 banner?: ReactNode;
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1784 /** Whether the person folded the sidebar away, as their cookie says. */
1785 sidebarClosed?: boolean;
A quicker settings slide: the same curve over 380ms1786 children: ReactNode;
1787}) {
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1788 const { pathname } = useLocation();
A quicker settings slide: the same curve over 380ms1789 const [drawer, setDrawer] = useState(false);
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1790 const [closed, setClosed] = useState(sidebarClosed);
A quicker settings slide: the same curve over 380ms1791 const [palette, setPalette] = useState(false);
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1792 const commands = useMemo(() => commandsFor(user, shell), [user, shell]);
A quicker settings slide: the same curve over 380ms1793
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1794 // A new page closes the drawer.
A quicker settings slide: the same curve over 380ms1795 useEffect(() => setDrawer(false), [pathname]);
Search across all of g1t, Explore, and a command palette1796 usePaletteShortcut(() => setPalette((open) => !open));
Merge branch 'worktree-agent-aca4790ea223aa235'1797 const leaving = useLeaving();
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)1798 useVisualViewport();
A quicker settings slide: the same curve over 380ms1799
Chat and workspace agents: channels, DMs and named agents you talk to1800 const going = useNavigation().location?.pathname;
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1801 const ws = shell.workspace;
1802 const mode = modeOf(going ?? pathname, ws?.slug ?? null);
1803 const panel = sidebarFor(mode, ws != null);
1804 const code = ws ? hasCodeAccess(ws) : false;
Chat and workspace agents: channels, DMs and named agents you talk to1805 const { sidebar: chatSidebar } = useChatSidebar();
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)1806 // Notify: the feed socket's live counts (lib/notify-client.ts) once it has them; the page's until then.
1807 const live = useLiveBadges(ws?.slug);
1808 const chatUnread = chatSidebar
1809 ? unreadTotals(chatSidebar.entries)
1810 : live?.chat != null
1811 ? { unread: live.chat, mentions: live.mentions ?? 0 }
1812 : (shell.chat ?? { unread: 0, mentions: 0 });
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1813 const notificationsUnread = live?.inbox ?? shell.inbox?.unread ?? 0;
1814 const unread = { notifications: notificationsUnread, chat: chatUnread.unread, mentions: chatUnread.mentions };
1815
1816 // Folding the sidebar away on a computer is remembered, so the next page is drawn the same from the server.
1817 const toggleSidebar = useCallback(() => {
1818 if (!window.matchMedia("(min-width: 1024px)").matches) {
1819 setDrawer((open) => !open);
1820 return;
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)1821 }
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1822 setClosed((was) => {
1823 document.cookie = sidebarCookie(!was, window.location.protocol === "https:");
1824 return !was;
1825 });
1826 }, []);
1827 useSidebarShortcut(useCallback(() => {
1828 if (panel) toggleSidebar();
1829 }, [panel, toggleSidebar]));
1830
1831 const inline = panel != null && !closed;
1832 const sidebarNode = () => {
1833 if (!panel) return null;
1834 if (!ws) return panel === "notifications" ? <NotificationsSidebar counts={shell.inbox ?? null} /> : <AccountSidebar username={user.username} />;
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)1835 switch (panel) {
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1836 case "code":
1837 return <CodeSidebar user={user} shell={shell} missing={missing} />;
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)1838 case "chat":
1839 return <ChatSidebar slug={ws.slug} />;
Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash.1840 case "artifacts":
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1841 return <FoliosSidebar slug={ws.slug} />;
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)1842 case "agents":
1843 return <AgentsSidebar slug={ws.slug} shellAgents={shell.agents ?? null} code={code} owner={ws.role === "owner"} />;
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1844 case "notifications":
1845 return <NotificationsSidebar counts={shell.inbox ?? null} />;
1846 case "people":
1847 return <PeopleSidebar slug={ws.slug} />;
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)1848 case "workspace":
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1849 return <WorkspaceSidebar slug={ws.slug} owner={ws.role === "owner"} />;
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)1850 case "account":
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1851 return <AccountSidebar username={user.username} />;
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)1852 }
1853 };
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1854 // The sidebar's top row: the workspace and its switcher, and the way to fold the sidebar or close the drawer.
1855 const sidebarTop = (inDrawer: boolean) => (
1856 <div className="flex h-14 shrink-0 items-center gap-1 pr-1 pl-1">
1857 {ws ? (
1858 <WorkspaceSwitcher user={user} workspace={ws} />
1859 ) : (
1860 <Link to="/" aria-label="g1t" className="mr-auto flex h-9 items-center rounded-md px-2">
1861 <Logo className="text-[1.125rem]" />
1862 </Link>
1863 )}
1864 {inDrawer ? (
1865 <button type="button" aria-label="Close menu" onClick={() => setDrawer(false)} className="flex size-8 shrink-0 items-center justify-center rounded-md text-faint hover:bg-raised hover:text-fg">
1866 <X size={16} />
1867 </button>
1868 ) : (
1869 <SidebarToggle open onClick={toggleSidebar} />
1870 )}
1871 </div>
1872 );
1873
1874 // On a phone (below 768px): the bottom bar, and a conversation full screen.
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)1875 const conversation = isConversation(going ?? pathname);
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1876 // Where the page panel starts: 8px past the dock (88px), or right after the sidebar (260px) when it is open.
1877 const left = ws ? (inline ? "md:left-24 lg:left-[21.75rem]" : "md:left-24") : inline ? "md:left-2 lg:left-[16.75rem]" : "md:left-2";
1878 const pad = ws ? (inline ? "md:pl-24 lg:pl-[21.75rem]" : "md:pl-24") : inline ? "md:pl-2 lg:pl-[16.75rem]" : "md:pl-2";
Chat and workspace agents: channels, DMs and named agents you talk to1879
A quicker settings slide: the same curve over 380ms1880 return (
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1881 // The drawer is a sheet: a dialog that holds focus, closes on Escape or
1882 // a tap outside, and gives focus back to the button that opened it.
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1883 <Sheet open={drawer} onOpenChange={setDrawer}>
A quicker settings slide: the same curve over 380ms1884 <Progress />
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1885 {ws && (
1886 <div className="fixed top-2 bottom-2 left-2 z-40 hidden w-20 md:block">
1887 <Dock
1888 workspace={ws}
1889 pins={shell.pins ?? []}
1890 unread={unread}
1891 account={<AccountMenu user={user} />}
1892 />
1893 </div>
1894 )}
1895 {panel && (
1896 <aside
1897 aria-label={`${MODE_MENU[panel]} sidebar`}
1898 className={`fixed inset-y-0 z-40 hidden w-[16.25rem] flex-col pr-0.5 pl-1.5 ${ws ? "left-[5.5rem]" : "left-0"} ${inline ? "lg:flex" : ""}`}
1899 >
1900 {sidebarTop(false)}
1901 <div className="min-h-0 grow">{sidebarNode()}</div>
1902 </aside>
1903 )}
Chat and workspace agents: channels, DMs and named agents you talk to1904 <SheetContent
1905 side="left"
1906 showClose={false}
1907 aria-describedby={undefined}
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1908 // Focus would land on the workspace's switcher and open its menu's hint; the sheet itself takes it instead.
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)1909 onOpenAutoFocus={(event) => {
1910 event.preventDefault();
1911 (event.currentTarget as HTMLElement | null)?.focus();
1912 }}
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1913 className="flex w-[min(18.5rem,86vw)] flex-col border-line bg-shell px-1.5 pb-[env(safe-area-inset-bottom)] max-md:[&_nav_a]:min-h-10"
Chat and workspace agents: channels, DMs and named agents you talk to1914 >
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1915 <SheetTitle className="sr-only">{panel ? `${MODE_MENU[panel]} menu` : "Menu"}</SheetTitle>
1916 {sidebarTop(true)}
1917 <div className="min-h-0 grow">{sidebarNode()}</div>
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1918 </SheetContent>
A quicker settings slide: the same curve over 380ms1919
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1920 <div className={`min-h-dvh px-1.5 pt-(--frame-top) pb-(--tabbar-h) md:pr-2 ${pad}`}>
1921 <div className="flex min-h-[calc(100dvh-var(--frame-top)-var(--tabbar-h))] min-w-0 flex-col rounded-[14px] bg-bg">
1922 <header
1923 className={`sticky top-(--frame-top) z-30 flex h-14 items-center gap-1.5 rounded-t-[14px] border-b border-line bg-bg pr-2 pl-2 sm:gap-2 sm:pr-3 ${conversation ? "max-md:hidden" : ""}`}
A quicker settings slide: the same curve over 380ms1924 >
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1925 {panel && (
1926 <SidebarToggle open={drawer} onClick={toggleSidebar} className={inline ? "lg:hidden" : ""} />
1927 )}
1928 {ws && (
1929 <span className={`flex min-w-0 shrink items-center gap-1.5 ${inline ? "lg:hidden" : ""}`}>
1930 <WorkspaceSwitcher user={user} workspace={ws} compact />
1931 <span aria-hidden="true" className="text-line-strong">
1932 /
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)1933 </span>
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1934 </span>
Inbox: a bell in the top bar opens it beside the page, and /inbox holds it all1935 )}
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1936 <Breadcrumbs pathname={pathname} missing={missing} repo={shell.repo} workspace={ws?.slug ?? null} />
1937 <div className="ml-auto flex shrink-0 items-center gap-1.5">
1938 <button
1939 type="button"
1940 aria-label="Search or jump to"
1941 onClick={() => setPalette(true)}
1942 className="flex h-8 items-center gap-2 rounded-md text-faint transition-colors hover:text-muted max-md:w-8 max-md:justify-center max-md:hover:bg-raised md:w-[min(17rem,26vw)] md:border md:border-line md:bg-surface md:px-2.5 md:hover:border-line-strong"
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put1943 >
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1944 <Search size={15} className="shrink-0" />
1945 <span className="hidden grow truncate text-left text-[0.8125rem] md:inline">Search or jump to</span>
1946 <PaletteKey className="hidden rounded bg-raised px-1.5 font-mono text-[0.625rem] text-muted ring-1 ring-line md:inline" />
1947 </button>
1948 {ws && <AskG1tButton slug={ws.slug} />}
1949 {/* On a phone, Notifications is in the bottom bar. */}
1950 <span className="max-md:hidden">
1951 <NotificationsBell counts={shell.inbox ? { ...shell.inbox, unread: notificationsUnread } : null} />
1952 </span>
1953 <CreateMenu shell={shell} />
1954 {/* Without a workspace there is no dock: the account is here. */}
1955 {!ws && <AccountMenu user={user} side="bottom" />}
1956 </div>
1957 </header>
1958 {banner}
1959 <main id="content" tabIndex={-1} {...leaving} className={`min-w-0 grow outline-none ${leaving.className}`}>
1960 <InMain.Provider value={true}>{children}</InMain.Provider>
1961 </main>
1962 </div>
A quicker settings slide: the same curve over 380ms1963 </div>
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1964 {/* The panel's edge: a rounded frame over the page, with the background beyond it, so what scrolls stays inside. */}
1965 {!conversation && (
1966 <div
1967 aria-hidden="true"
1968 className={`pointer-events-none fixed top-(--frame-top) right-1.5 bottom-(--tabbar-h) left-1.5 z-[35] rounded-[14px] shadow-[0_0_0_1px_var(--color-line),0_0_0_100vmax_var(--color-shell)] md:right-2 ${left}`}
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 bar1969 />
1970 )}
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1971 {ws && <BottomBar user={user} workspace={ws} pins={shell.pins ?? []} unread={unread} onReselect={panel ? () => setDrawer(true) : undefined} />}
1972 <CommandPalette open={palette} onOpenChange={setPalette} commands={commands} repo={shell.repo ? `${shell.repo.namespace}/${shell.repo.name}` : null} />
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1973 </Sheet>
A quicker settings slide: the same curve over 380ms1974 );
1975}
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.1976
1977/** Create new: a project, an issue in the one you are in, a workspace or a team. */
1978function CreateMenu({ shell }: { shell: ShellData }) {
1979 return (
1980 <DropdownMenu>
1981 <Hint label="Create new">
1982 <DropdownMenuTrigger
1983 aria-label="Create new"
1984 className="flex h-8 items-center gap-1 rounded-md border border-line px-1.5 text-fg/90 outline-none transition-colors hover:border-line-strong hover:bg-raised hover:text-fg focus-visible:ring-2 focus-visible:ring-accent data-[state=open]:bg-raised sm:px-2"
1985 >
1986 <Plus size={16} />
1987 <ChevronDown size={13} className="text-muted max-sm:hidden" />
1988 </DropdownMenuTrigger>
1989 </Hint>
1990 <DropdownMenuContent align="end" className="min-w-52">
1991 {shell.repo && (
1992 <>
1993 <DropdownMenuLabel className="truncate">In {shell.repo.name}</DropdownMenuLabel>
1994 <DropdownMenuItem asChild>
1995 <Link to={`/${shell.repo.namespace}/${shell.repo.name}/issues/new`}>
1996 <CircleDot />
1997 New issue
1998 </Link>
1999 </DropdownMenuItem>
2000 {shell.repo.member && (
2001 <DropdownMenuItem asChild>
2002 <Link to={`/${shell.repo.namespace}/${shell.repo.name}/plans`}>
2003 <ListTree />
2004 Plan work
2005 </Link>
2006 </DropdownMenuItem>
2007 )}
2008 <DropdownMenuSeparator />
2009 </>
2010 )}
2011 <DropdownMenuItem asChild>
2012 <Link to="/?agent=new">
2013 <Sparkles />
2014 Put an agent on it
2015 </Link>
2016 </DropdownMenuItem>
2017 <DropdownMenuItem asChild>
2018 <Link to="/new">
2019 <Box />
2020 New project
2021 </Link>
2022 </DropdownMenuItem>
2023 <DropdownMenuItem asChild>
2024 <Link to="/new/github">
2025 <GitBranch />
2026 Import from GitHub
2027 </Link>
2028 </DropdownMenuItem>
2029 <DropdownMenuSeparator />
2030 <DropdownMenuItem asChild>
2031 <Link to="/workspaces/new">
2032 <Users />
2033 New workspace
2034 </Link>
2035 </DropdownMenuItem>
2036 {/* A team in the workspace you are in, for whoever it lets create one. */}
2037 {shell.workspace &&
2038 (mayCreateTeams(shell.workspace.team_creation, shell.workspace.role) ? (
2039 <DropdownMenuItem asChild>
2040 <Link to={`/${shell.workspace.slug}/-/teams/new`}>
2041 <UsersRound />
2042 New team
2043 </Link>
2044 </DropdownMenuItem>
2045 ) : (
2046 <DropdownMenuItem disabled>
2047 <UsersRound />
2048 New team
2049 <span className="ml-auto pl-3 text-xs text-faint">Owners only</span>
2050 </DropdownMenuItem>
2051 ))}
2052 </DropdownMenuContent>
2053 </DropdownMenu>
2054 );
2055}

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