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

People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.1import { Activity, BarChart3, Building2, MessagesSquare, Bell, BookMarked, BookOpen, Bookmark, Blocks, Bot, Box, Check, ChevronDown, ChevronLeft, ChevronRight, CircleDot, GripVertical, CircleUserRound, Code2, Coins, 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, Store, Sun, Ticket, TrendingUp, UserPlus, UserRoundKey, Users, UsersRound, Webhook, X, ArrowLeftRight } from "lucide-react";
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.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";
Sidebar: no settings flash on the way into a repository, and a better slide4
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";
Sidebar: no settings flash on the way into a repository, and a better slide6
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";
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.10import { SpendPill } from "./spend";
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar11import { PinButton } from "./pin-button";
Merge branch 'worktree-agent-ae1299e92e4462012'12import { 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.13import { Sheet, SheetContent, SheetTitle } from "./ui/sheet";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas14import { 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.15import { Logo } from "./logo";
Usage, Billing settings and prepaid AI credit; fixes from the UX audit16import { Avatar, SoonPill } from "./ui";
Fast pages, required checks on the branch, self-hosted runners, honest incidents17import { Skeleton } from "./ui/skeleton";
Sidebar: no settings flash on the way into a repository, and a better slide18import {
19 DropdownMenu,
20 DropdownMenuContent,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas21 DropdownMenuGroup,
Sidebar: no settings flash on the way into a repository, and a better slide22 DropdownMenuItem,
23 DropdownMenuLabel,
24 DropdownMenuSeparator,
25 DropdownMenuTrigger,
26} from "./ui/dropdown-menu";
Merge branch 'worktree-agent-ad7c6d88d93adc817'27import { 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.28import { type ModeKey, SETTINGS_PAGES, modeOf, todayPath } from "../lib/workspace-nav";
Chat and workspace agents: channels, DMs and named agents you talk to29import { AgentsSidebar } from "./agents-mode";
30import { 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.31import { 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.32import { 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)33import { 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.34import { BottomBar, isConversation, useVisualViewport } from "./mobile";
Chat and workspace agents: channels, DMs and named agents you talk to35import { useChatSidebar } from "./chat/actions";
36import { unreadTotals } from "../lib/chat";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look37import { 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.38import { projectPages } from "../lib/chrome";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas39import { 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.40import { type PinnableApp, sidebarCookie } from "../lib/apps";
41import { 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 quotas42import { 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.43import { useInviteOnly } from "../lib/registration";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas44import { STATUS_URL, statusTitle } from "../lib/status";
Navigation: the workspace's own page with tabs, pins and recent in the sidebar45import { 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 quotas46import 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)47import { 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 managers48import { OwnPresenceDot, OwnPresenceItems, StatusDialog } from "./presence";
You choose how g1t looks: Auto follows your system, Light and Dark stay put, set from the account menu, the phone's You and help sheet, Settings → Account or the command palette; the page is drawn in your choice from the first byte, every colour has a light value that reads at 4.5:1 or better, code and diffs are highlighted for both, diagrams and the document editor follow along, the product tour and the g1t mark's avatar stay dark, and Dark is what you see until you choose; the workspaces guide says how.49import { THEME_COMMANDS, ThemeMenuSwitch } from "./theme-switch";
Sidebar: no settings flash on the way into a repository, and a better slide50
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put51/**
52 * What the sidebar needs, worked out by the root loader. For a visitor who
53 * is not signed in there is no workspace, no projects and no usage: only
54 * the project being looked at, if they can see it.
55 */
Sidebar: no settings flash on the way into a repository, and a better slide56export type ShellData = {
57 /** The workspace the sidebar is about: the one being looked at, or their first. */
Workspace names and icons, and a component kit for every control58 workspace: Membership | null;
Navigation: the workspace's own page with tabs, pins and recent in the sidebar59 /** All its projects, by name, for the palette: `name` is the slug in their address. */
60 repos: ShortcutProject[];
61 /** The person's pinned projects in it, in their order (lib/pins.ts). */
62 pinned?: ShortcutProject[];
63 /** What they opened there last, latest first, leaving out the pinned. */
64 recent?: ShortcutProject[];
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look65 /** Repositories shared with them in workspaces they do not belong to. */
66 shared?: { namespace: string; name: string; isPrivate: boolean }[];
Projects: what a workspace builds and runs, first on every page67 /** The project being looked at, if any, whoever owns it. */
Sidebar: no settings flash on the way into a repository, and a better slide68 repo: {
69 namespace: string;
70 name: string;
71 member: boolean;
72 issues: number;
73 pulls: number;
74 } | null;
Billing accounts, terms and enterprises; g1t is no longer free75 /** Where the workspace stands against its usage limit, if billing is on. */
76 limit: {
77 exposureMicros: number;
78 ceilingMicros: number | null;
79 state: "ok" | "warning" | "stopped";
80 comped: boolean;
81 } | null;
Sidebar: no settings flash on the way into a repository, and a better slide82 /** Whether g1t charges nothing for now, while it is being built out. */
83 free?: boolean;
84 /** What its agents have cost since the start of the month. */
Usage while free is shown at cost; agents get rustfmt and clippy85 /** This month's usage: charged, or at cost while g1t is free. */
86 monthUsageMicros: number | null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look87 /** Whether new compute is paused (a spend spike or a hold), and whether the viewer can answer it. */
88 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.89 /** 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 all90 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)91 /**
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.92 * 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)93 * starred and latest conversations. Null when chat did not answer in time.
94 */
95 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.96 /** 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)97 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.98 /** The apps this person pinned to their dock in the workspace (lib/apps.ts). */
99 pins?: PinnableApp[];
Sidebar: no settings flash on the way into a repository, and a better slide100};
101
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)102/** An agent as the shell lists it. */
103export type ShellAgent = Pick<
104 WorkspaceAgent,
105 "id" | "handle" | "display_name" | "avatar" | "avatar_seed" | "role" | "status" | "title" | "team" | "department" | "builtin"
106>;
107
Sidebar: no settings flash on the way into a repository, and a better slide108function SidebarLink({
109 to,
110 icon,
111 end,
112 count,
113 also,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look114 drill,
Merge branch 'worktree-agent-ad7c6d88d93adc817'115 current: lit,
Sidebar: no settings flash on the way into a repository, and a better slide116 children,
117}: {
118 to: string;
119 icon: ReactNode;
120 end?: boolean;
121 count?: number;
Projects: what a workspace builds and runs, first on every page122 /** Other path prefixes under which this link is the current one. */
123 also?: string | string[];
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look124 /** It opens a list of its own: a chevron says so, always or on hover. */
125 drill?: boolean | "hover";
Merge branch 'worktree-agent-ad7c6d88d93adc817'126 /** Whether it is the current row, when the list works that out itself. */
127 current?: boolean;
Sidebar: no settings flash on the way into a repository, and a better slide128 children: ReactNode;
129}) {
130 const { pathname } = useLocation();
Opening Notifications lights only the row you chose: a sidebar whose rows differ only by their query shows a row as loading only when the page on its way is that row's, not every row on the same path.131 const navigation = useNavigation();
132 // NavLink's own pending state compares paths only, so a list whose rows
133 // differ by query (Notifications' views and reasons) would light every
134 // row while one loads. Where the list says which row is current, a row
135 // is pending only when the page on its way is that row's, query and all.
136 const loading = navigation.location;
137 const pendingHere = loading != null && `${loading.pathname}${loading.search}` === to;
Sidebar: no settings flash on the way into a repository, and a better slide138 return (
139 <NavLink
140 to={to}
141 end={end}
142 prefetch="intent"
143 className={({ isActive, isPending }) => {
Projects: what a workspace builds and runs, first on every page144 const current =
Merge branch 'worktree-agent-ad7c6d88d93adc817'145 lit ??
146 (isActive || [also ?? []].flat().some((prefix) => pathname === prefix || pathname.startsWith(prefix + "/")));
Opening Notifications lights only the row you chose: a sidebar whose rows differ only by their query shows a row as loading only when the page on its way is that row's, not every row on the same path.147 const pending = lit === undefined ? isPending : pendingHere;
Sidebar: no settings flash on the way into a repository, and a better slide148 return `group flex h-8 items-center gap-2.5 rounded-md px-2 text-[0.8125rem] transition-colors ${
149 current
150 ? "bg-raised font-medium text-fg"
Opening Notifications lights only the row you chose: a sidebar whose rows differ only by their query shows a row as loading only when the page on its way is that row's, not every row on the same path.151 : pending
Sidebar: no settings flash on the way into a repository, and a better slide152 ? "bg-raised/60 text-fg"
153 : "text-muted hover:bg-raised/60 hover:text-fg"
154 }`;
155 }}
156 >
157 <span className="shrink-0 text-faint group-hover:text-muted">{icon}</span>
158 <span className="min-w-0 grow truncate">{children}</span>
159 {count != null && count > 0 && (
160 <span className="rounded bg-line px-1.5 text-[0.6875rem] tabular-nums text-muted">
161 {count}
162 </span>
163 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look164 {drill && (
165 <ChevronRight
166 size={14}
167 aria-hidden="true"
168 className={`-mr-0.5 shrink-0 text-faint transition-opacity ${drill === "hover" ? "opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" : ""}`}
169 />
170 )}
Sidebar: no settings flash on the way into a repository, and a better slide171 </NavLink>
172 );
173}
174
Pull requests say where they are live; the project menu shows what is coming175/**
176 * Something a project will have, shown where it will live so people can
177 * see where g1t is going. Not a link: nothing is behind it yet.
178 */
179function SidebarSoon({ icon, children, about }: { icon: ReactNode; children: ReactNode; about: string }) {
180 return (
Merge branch 'worktree-agent-ae1299e92e4462012'181 <Hint label={about} side="right">
182 <div aria-disabled="true" className="flex h-8 cursor-default items-center gap-2.5 rounded-md px-2 text-[0.8125rem] text-faint">
183 <span className="shrink-0 opacity-70">{icon}</span>
184 <span className="grow truncate">{children}</span>
185 <span className="sr-only">{about}</span>
186 <SoonPill />
187 </div>
188 </Hint>
Pull requests say where they are live; the project menu shows what is coming189 );
190}
191
The project menu opens by section, and the workspace has its own panel192/**
A flat project menu with Code first, views as tabs, and Stripe for every owner193 * A page that is coming, as a link to its roadmap page: faint, with Soon,
194 * and marked current on any of its section's Soon pages.
The project menu opens by section, and the workspace has its own panel195 */
A flat project menu with Code first, views as tabs, and Stripe for every owner196function SidebarSoonLink({
The project menu opens by section, and the workspace has its own panel197 to,
198 also,
A flat project menu with Code first, views as tabs, and Stripe for every owner199 icon,
200 about,
Merge branch 'worktree-agent-ad7c6d88d93adc817'201 current: lit,
The project menu opens by section, and the workspace has its own panel202 children,
203}: {
204 to: string;
A flat project menu with Code first, views as tabs, and Stripe for every owner205 also?: string[];
206 icon: ReactNode;
207 about: string;
Merge branch 'worktree-agent-ad7c6d88d93adc817'208 /** Whether it is the current row, when the list works that out itself. */
209 current?: boolean;
The project menu opens by section, and the workspace has its own panel210 children: ReactNode;
211}) {
212 const { pathname } = useLocation();
213 return (
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero214 // The hint wraps a plain box: Radix's asChild merges className as a
215 // string, which would break NavLink's className function.
Merge branch 'worktree-agent-ae1299e92e4462012'216 <Hint label={about} side="right">
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero217 <div>
The project menu opens by section, and the workspace has its own panel218 <NavLink
219 to={to}
220 prefetch="intent"
A flat project menu with Code first, views as tabs, and Stripe for every owner221 className={({ isActive }) => {
Merge branch 'worktree-agent-ad7c6d88d93adc817'222 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 owner223 return `group flex h-8 items-center gap-2.5 rounded-md px-2 text-[0.8125rem] transition-colors ${
224 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 panel225 }`;
226 }}
227 >
A flat project menu with Code first, views as tabs, and Stripe for every owner228 <span className="shrink-0 opacity-80">{icon}</span>
The project menu opens by section, and the workspace has its own panel229 <span className="min-w-0 grow truncate">{children}</span>
Usage, Billing settings and prepaid AI credit; fixes from the UX audit230 <SoonPill />
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales231 </NavLink>
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero232 </div>
Merge branch 'worktree-agent-ae1299e92e4462012'233 </Hint>
The project menu opens by section, and the workspace has its own panel234 );
235}
236
A flat project menu with Code first, views as tabs, and Stripe for every owner237/** Icons for what spans projects. */
238const WORKSPACE_ICONS: Record<string, ReactNode> = {
239 board: <KanbanSquare size={15} />,
240 roadmap: <GanttChart size={15} />,
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member241 teams: <UsersRound size={15} />,
A flat project menu with Code first, views as tabs, and Stripe for every owner242 packages: <Package size={15} />,
243 fleet: <Bot size={15} />,
244};
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales245
A flat project menu with Code first, views as tabs, and Stripe for every owner246/** The Soon pages of a section, as paths, so its link is current on them. */
247function soonPaths(base: string, section: RoadmapItem["section"]): string[] {
248 return roadmapIn(section).map((item) => `${base}/soon/${item.key}`);
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales249}
250
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look251function SidebarGroup({
252 title,
253 action,
254 className = "",
255 children,
256}: {
257 title: string;
258 action?: ReactNode;
259 className?: string;
260 children: ReactNode;
261}) {
Sidebar: no settings flash on the way into a repository, and a better slide262 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look263 <section className={className}>
Sidebar: no settings flash on the way into a repository, and a better slide264 <div className="mb-1 flex h-6 items-center justify-between px-2">
265 <h2 className="text-xs font-medium text-faint">{title}</h2>
266 {action}
267 </div>
268 <div className="space-y-px">{children}</div>
269 </section>
270 );
271}
272
Workspace names and icons, and a component kit for every control273/** What a workspace is called where people read it: its display name, else its slug. */
274function displayName(membership: Membership): string {
275 return membership.name?.trim() || membership.slug;
Sidebar: no settings flash on the way into a repository, and a better slide276}
277
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas278/**
279 * The fine print, as one quiet row at the foot of the account menu and the
280 * visitor's panel: each link a full-height target, left-aligned. In the
281 * menu each is a menu item, so the arrow keys reach it.
282 */
283const LEGAL_LINKS: [string, string][] = [
284 ["Policies", "/policies"],
285 ["Privacy", "/policies/privacy"],
286 ["Security", "/security"],
287];
288const LEGAL_LINK = "flex h-7 items-center rounded px-1.5 text-xs text-faint outline-none transition-colors";
289
290function MenuLegalRow() {
291 return (
292 <div role="group" aria-label="Legal" className="flex items-center gap-0.5 px-0.5 pt-0.5">
293 {LEGAL_LINKS.map(([label, to], index) => (
294 <span key={to} className="flex items-center gap-0.5">
295 {index > 0 && (
296 <span aria-hidden="true" className="text-[0.625rem] text-line-strong">
297 ·
298 </span>
299 )}
300 <DropdownMenuItem asChild className={`${LEGAL_LINK} py-0 data-highlighted:bg-line data-highlighted:text-fg`}>
301 <Link to={to}>{label}</Link>
302 </DropdownMenuItem>
303 </span>
304 ))}
305 </div>
306 );
307}
308
309/** Status's row: the live dot and two or three words, fetched when the menu opens. */
310function StatusSummary({ open }: { open: boolean }) {
311 const status = useSiteStatus(open);
312 const words = statusTitle(status);
313 return (
314 <span className="ml-auto flex min-w-0 items-center gap-1.5 pl-2 text-xs text-faint">
315 {/* The words say it; the dot's own words for screen readers would repeat them. */}
316 <span aria-hidden="true" className="flex">
317 <StatusDot state={status?.overall.state ?? null} />
318 </span>
Fast pages, required checks on the branch, self-hosted runners, honest incidents319 {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 quotas320 </span>
321 );
322}
323
324/** A menu row: an icon, words, and whatever sits at its end. */
325const MENU_ROW = "h-9 gap-2.5 px-2.5 text-[0.8125rem]";
326
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.327/**
328 * Your account, at the foot of the dock (or in the header, before you have
329 * a workspace): who you are and your status, your profile and settings,
330 * and help: the documentation, support, status and the keyboard's
331 * shortcuts; then signing out and the fine print.
332 */
333function AccountMenu({ user, side = "right" }: { user: User; side?: "right" | "bottom" }) {
Sidebar: no settings flash on the way into a repository, and a better slide334 const submit = useSubmit();
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas335 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.336 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 managers337 // Your status's dialog: outside the menu, so the menu closes behind it.
338 const [editing, setEditing] = useState(false);
Fast pages, required checks on the branch, self-hosted runners, honest incidents339 // Name, primary address and invites left: asked for once, as soon as the
340 // 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 quotas341 const details = useFetcher<AccountMenuData | null>({ key: "account-menu" });
Fast pages, required checks on the branch, self-hosted runners, honest incidents342 const prefetch = () => {
343 if (details.state === "idle" && details.data === undefined) details.load("/settings/menu.json");
344 };
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas345 useEffect(() => {
Fast pages, required checks on the branch, self-hosted runners, honest incidents346 if (open) prefetch();
347 // eslint-disable-next-line react-hooks/exhaustive-deps
348 }, [open]);
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas349 const me = details.data ?? null;
Fast pages, required checks on the branch, self-hosted runners, honest incidents350 // Still on its way: shapes where the words will be, the same size.
351 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)352 // While anyone can sign up, listed once the data says there are invites to look back on.
353 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 quotas354 const profile = `/u/${user.username}`;
Sidebar: no settings flash on the way into a repository, and a better slide355 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 managers356 <>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas357 <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.358 {/* 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 quotas359 <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 managers360 aria-label={`Account menu for ${shownUsername(user)}`}
Fast pages, required checks on the branch, self-hosted runners, honest incidents361 onPointerEnter={prefetch}
362 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.363 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 quotas364 >
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.365 <Avatar name={user.username} image={user.avatar} size={side === "right" ? 32 : 28} />
366 <OwnPresenceDot ring={side === "right" ? "var(--color-dock)" : "var(--color-bg)"} className="absolute -right-0.5 -bottom-0.5" />
Sidebar: no settings flash on the way into a repository, and a better slide367 </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.368 <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 quotas369 {/* Who is signed in, and a way to their profile. */}
370 <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 managers371 <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 quotas372 <Avatar name={user.username} image={user.avatar} size={36} />
Fast pages, required checks on the branch, self-hosted runners, honest incidents373 <span className="flex min-w-0 grow flex-col leading-tight" aria-busy={loading}>
374 {loading ? (
375 <Skeleton className="my-[0.1875rem] h-3.5 w-28" />
376 ) : (
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers377 <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 incidents378 )}
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 <span className="truncate font-mono text-xs text-muted">@{shownUsername(user)}</span>
Fast pages, required checks on the branch, self-hosted runners, honest incidents380 {loading ? (
381 <Skeleton className="mt-1 h-3 w-40" />
382 ) : (
383 me?.email && <span className="mt-0.5 truncate text-xs text-faint">{me.email}</span>
384 )}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas385 </span>
Sidebar: no settings flash on the way into a repository, and a better slide386 </Link>
387 </DropdownMenuItem>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas388 <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 managers389 {/* Your status, away, and pausing notifications. */}
390 <DropdownMenuGroup>
391 <OwnPresenceItems className="min-h-9 py-1.5 text-[0.8125rem]" onEdit={() => setEditing(true)} />
392 </DropdownMenuGroup>
393 <DropdownMenuSeparator className="my-1.5" />
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas394 <DropdownMenuGroup>
395 <DropdownMenuItem asChild className={MENU_ROW}>
396 <Link to={profile}>
397 <CircleUserRound />
398 Your profile
399 </Link>
400 </DropdownMenuItem>
401 <DropdownMenuItem asChild className={MENU_ROW}>
402 <Link to={FIRST_SETTINGS_PAGE}>
403 <Settings />
404 Your settings
405 </Link>
406 </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)407 {invitesListed && (
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas408 <DropdownMenuItem asChild className={MENU_ROW}>
409 <Link to="/settings/invites">
410 <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)411 {ACCOUNT_SETTINGS.invites.title}
Fast pages, required checks on the branch, self-hosted runners, honest incidents412 {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 quotas413 {me?.invites_left != null && (
414 <span className="ml-auto rounded-full bg-line px-1.5 text-[0.6875rem] tabular-nums text-muted">
415 {me.invites_left} left
416 </span>
417 )}
418 </Link>
419 </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)420 )}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas421 </DropdownMenuGroup>
422 <DropdownMenuSeparator className="my-1.5" />
You choose how g1t looks: Auto follows your system, Light and Dark stay put, set from the account menu, the phone's You and help sheet, Settings → Account or the command palette; the page is drawn in your choice from the first byte, every colour has a light value that reads at 4.5:1 or better, code and diffs are highlighted for both, diagrams and the document editor follow along, the product tour and the g1t mark's avatar stay dark, and Dark is what you see until you choose; the workspaces guide says how.423 {/* Auto, Light or Dark, switched in place (lib/theme.ts). */}
424 <ThemeMenuSwitch />
425 <DropdownMenuSeparator className="my-1.5" />
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas426 <DropdownMenuGroup>
427 <DropdownMenuItem asChild className={MENU_ROW}>
428 <a href="https://docs.g1t.sh/">
429 <BookOpen />
430 Documentation
431 </a>
432 </DropdownMenuItem>
433 <DropdownMenuItem asChild className={MENU_ROW}>
434 <Link to="/support">
435 <LifeBuoy />
436 Support
437 </Link>
438 </DropdownMenuItem>
439 <DropdownMenuItem asChild className={MENU_ROW}>
440 <a href={STATUS_URL}>
441 <Activity />
442 Status
443 <StatusSummary open={open} />
444 </a>
445 </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.446 <DropdownMenuItem className={MENU_ROW} onSelect={() => setKeys(true)}>
447 <Keyboard />
448 Keyboard shortcuts
449 <PaletteKey className="ml-auto font-sans text-xs text-faint" />
450 </DropdownMenuItem>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas451 </DropdownMenuGroup>
452 <DropdownMenuSeparator className="my-1.5" />
Sidebar: no settings flash on the way into a repository, and a better slide453 {/* Submitted from here: the menu closes on select, and a button
454 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 quotas455 <DropdownMenuItem className={MENU_ROW} onSelect={() => submit(null, { method: "post", action: "/logout" })}>
Sidebar: no settings flash on the way into a repository, and a better slide456 <LogOut />
457 Sign out
458 </DropdownMenuItem>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas459 <DropdownMenuSeparator className="my-1.5" />
460 <MenuLegalRow />
Sidebar: no settings flash on the way into a repository, and a better slide461 </DropdownMenuContent>
462 </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 managers463 <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.464 <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 managers465 </>
Sidebar: no settings flash on the way into a repository, and a better slide466 );
467}
468
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look469/**
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar470 * A workspace's settings pages, which the sidebar drills into: how it is
The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how.471 * set up and connected (guardrails, secrets, integrations,
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar472 * webhooks), what it pays, its repositories, tokens and record. The main
473 * list keeps the places work happens and who belongs; every member can
474 * still open these.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look475 */
Mission control counts people's own changes as theirs; a shorter sidebar with setup under Settings, and a 56px top bar476const SETTINGS_PAGE =
Merge branch 'worktree-agent-ad7c6d88d93adc817'477 new RegExp(`^/([^/]+)/-/(${SETTINGS_PAGES.join("|")})(/|$)`);
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look478/** A project's settings pages, which the project's menu drills into. */
Project settings move into the sidebar, grouped, with a heading per page479const REPO_SETTINGS_PAGE = /^\/([^/]+)\/([^/-][^/]*)\/settings(\/|$)/;
Sidebar: no settings flash on the way into a repository, and a better slide480
481/**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look482 * The sidebar's lists are a stack, the way a phone pushes a screen: one
483 * drilled into slides in from the right over the full width, while the one
484 * it covers drifts a quarter of the way left and fades, both on one long
Sidebar: the panels really slide485 * ease-out, the fade quicker than the move so the two never blur together.
486 * Going back reverses it.
Sidebar: no settings flash on the way into a repository, and a better slide487 */
488const LAYER =
Sidebar: the panels really slide489 "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 look490/** One list, filling its layer. */
Sidebar: no settings flash on the way into a repository, and a better slide491const PANEL = "h-full overflow-y-auto px-2 pb-4";
492
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look493/** One list in the stack: what it is, and its rows. */
494type Level = { key: string; node: ReactNode };
495
496/** True once the page has hydrated, so what the server drew never animates in. */
497function useHydrated(): boolean {
498 const [hydrated, setHydrated] = useState(false);
499 useEffect(() => setHydrated(true), []);
500 return hydrated;
501}
502
503/**
504 * Drilling in and out of the sidebar's lists. `trail` is the way from the
505 * main list to the one shown, worked out from the address, so a link
506 * straight to a settings page opens the sidebar already drilled in, and
507 * leaving it comes back out. Lists deeper than the one shown stay in
508 * place, off to the right, so going back slides them away rather than
509 * dropping them. Moving to a list at the same depth (a workspace's settings
510 * to a project) fades the new one in where it is.
511 */
512function Drill({ trail }: { trail: Level[] }) {
513 const depth = trail.length - 1;
514 const hydrated = useHydrated();
515 const stack = useRef<Level[]>(trail);
516 const before = stack.current;
517 const within = trail.every((level, index) => before[index]?.key === level.key);
518 stack.current = within ? [...trail, ...before.slice(trail.length)] : trail;
519 const levels = stack.current;
520 // What was showing last time, to tell drilling in from moving across.
521 const shown = useRef({ depth, keys: levels.map((level) => level.key) });
522 useEffect(() => {
523 shown.current = { depth, keys: levels.map((level) => level.key) };
524 });
Sidebar: no settings flash on the way into a repository, and a better slide525 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look526 <div className="relative min-h-0 grow overflow-hidden">
527 {levels.map((level, index) => {
528 const current = index === depth;
529 const place =
530 index < depth
531 ? "pointer-events-none -translate-x-1/4 opacity-0"
532 : current
533 ? "translate-x-0 opacity-100"
534 : "pointer-events-none translate-x-full opacity-0";
535 // A list that was not there before arrives: from the right when
536 // drilling in, in place when moving across.
537 const arriving = hydrated && current && !shown.current.keys.includes(level.key);
538 const enter = arriving
539 ? depth > shown.current.depth
540 ? "starting:translate-x-full starting:opacity-0"
541 : "starting:opacity-0"
542 : "";
543 return (
544 <div key={level.key} className={`${LAYER} ${place} ${enter}`} inert={!current} aria-hidden={!current || undefined}>
545 {level.node}
546 </div>
547 );
548 })}
549 </div>
550 );
551}
552
553/**
554 * The row at the top of a list drilled into: the list's name, which goes
555 * back out, and what it belongs to, faint at the end.
556 */
557function BackRow({ to, label, context }: { to: string; label: ReactNode; context?: ReactNode }) {
558 return (
559 <Link
560 to={to}
561 prefetch="intent"
562 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"
Sidebar: no settings flash on the way into a repository, and a better slide563 >
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look564 <ChevronLeft size={16} className="shrink-0 text-faint transition-transform group-hover:-translate-x-0.5 group-hover:text-muted" />
565 <span className="min-w-0 shrink-0 truncate">{label}</span>
566 {context && (
567 <span className="ml-auto min-w-0 truncate pl-2 font-mono text-[0.6875rem] font-normal text-faint">{context}</span>
568 )}
569 </Link>
570 );
571}
572
573/** A thin rule between groups of a list. */
574function Rule() {
575 return <div role="separator" className="mx-2 my-2.5 h-px bg-line" />;
576}
577
Navigation: the workspace's own page with tabs, pins and recent in the sidebar578/** A quiet heading inside a group: Pinned, Recent. */
579function SidebarSubhead({ children }: { children: ReactNode }) {
580 return <h3 className="px-2 pt-1.5 pb-0.5 text-[0.6875rem] font-medium tracking-wide text-faint">{children}</h3>;
581}
582
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look583/**
Navigation: the workspace's own page with tabs, pins and recent in the sidebar584 * The workspace's projects as the sidebar keeps them, however many there
585 * are: the person's pins in their order, what they opened last, and the
586 * way to all of them. Pins move by dragging, or with Alt and the arrow
587 * keys; the projects service keeps the order.
588 */
Merge branch 'worktree-agent-ad7c6d88d93adc817'589function SidebarProjects({ slug, shell, current }: { slug: string; shell: ShellData; current: boolean }) {
Navigation: the workspace's own page with tabs, pins and recent in the sidebar590 const reorder = useFetcher({ key: `pins:${slug}` });
591 const saved = shell.pinned ?? [];
592 // While a new order is on its way, it shows as made.
593 const asked = reorder.formData?.get("intent") === "reorder" ? reorder.formData.getAll("slug").map(String) : null;
594 const pinned = asked
595 ? asked.map((name) => saved.find((project) => project.name === name)).filter((project): project is ShortcutProject => project != null)
596 : saved;
597 const active = shell.repo ? { namespace: shell.repo.namespace, name: shell.repo.name, isPrivate: false } : null;
598 const recent = recentWith(shell.recent ?? [], pinned, active, slug);
599 const [dragging, setDragging] = useState<number | null>(null);
600 const move = (from: number, by: number) => {
601 const next = movedPin(pinned, from, by);
602 if (!next) return;
603 const form = new FormData();
604 form.set("intent", "reorder");
605 for (const project of next) form.append("slug", project.name);
606 reorder.submit(form, { method: "post", action: `/${slug}/-/pins` });
607 };
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar608 // Each row pins or unpins in place: the pin shows on hover or focus, and
609 // stays shown on a pinned row's hover so it reads as "unpin".
610 const row = (project: ShortcutProject, isPinned: boolean) => (
611 <div className="group/row relative">
612 <SidebarLink to={`/${project.namespace}/${project.name}`} icon={project.isPrivate ? <Lock size={15} /> : <Box size={15} />} drill="hover">
613 <span className="block truncate pr-6">{project.title ?? project.name}</span>
614 </SidebarLink>
615 <PinButton
616 workspace={slug}
617 slug={project.name}
618 name={project.title ?? project.name}
619 pinned={isPinned}
620 small
621 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"
622 />
623 </div>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar624 );
625 return (
626 <SidebarGroup
627 title="Projects"
628 action={
New project and Import from GitHub work in the workspace you're in, as the sidebar shows it, with no workspace to pick on the page; a link that names another of your workspaces switches you to it first. The projects guide says so.629 <Link to="/new" aria-label="New project" className="rounded p-0.5 text-faint hover:bg-raised hover:text-fg">
Navigation: the workspace's own page with tabs, pins and recent in the sidebar630 <Plus size={13} />
631 </Link>
632 }
633 >
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar634 {/* Only there once something is pinned: each row below has its own pin. */}
635 {pinned.length > 0 && (
636 <>
637 <SidebarSubhead>Pinned</SidebarSubhead>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar638 <ul aria-label="Pinned projects" className="space-y-px">
639 {pinned.map((project, index) => (
640 <li
641 key={project.name}
642 draggable={pinned.length > 1}
643 onDragStart={(event) => {
644 setDragging(index);
645 event.dataTransfer.effectAllowed = "move";
646 }}
647 onDragOver={(event) => {
648 if (dragging != null) event.preventDefault();
649 }}
650 onDrop={(event) => {
651 event.preventDefault();
652 if (dragging != null && dragging !== index) move(dragging, index - dragging);
653 setDragging(null);
654 }}
655 onDragEnd={() => setDragging(null)}
656 onKeyDown={(event) => {
657 if (!event.altKey || (event.key !== "ArrowUp" && event.key !== "ArrowDown")) return;
658 event.preventDefault();
659 move(index, event.key === "ArrowUp" ? -1 : 1);
660 }}
661 className={`group/pin relative ${dragging === index ? "opacity-50" : ""}`}
662 >
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar663 {row(project, true)}
Navigation: the workspace's own page with tabs, pins and recent in the sidebar664 {pinned.length > 1 && (
Merge branch 'worktree-agent-ae1299e92e4462012'665 <Hint label="Drag, or Alt and an arrow key, to reorder" side="right">
666 <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">
667 <GripVertical size={12} aria-hidden="true" />
668 </span>
669 </Hint>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar670 )}
671 </li>
672 ))}
673 </ul>
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar674 </>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar675 )}
676 {recent.length > 0 && (
677 <>
678 <SidebarSubhead>Recent</SidebarSubhead>
679 {recent.map((project) => (
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar680 <div key={`${project.namespace}/${project.name}`}>{row(project, false)}</div>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar681 ))}
682 </>
683 )}
684 <div className="pt-1">
Merge branch 'worktree-agent-ad7c6d88d93adc817'685 <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 sidebar686 All projects
687 </SidebarLink>
688 </div>
689 </SidebarGroup>
690 );
691}
692
Merge branch 'worktree-agent-ad7c6d88d93adc817'693/** Insights, coming: the workspace's own page says what it will be. */
694const INSIGHTS = roadmapItem("insights");
695
Sidebar: no settings flash on the way into a repository, and a better slide696/**
697 * What the repository menu needs. Known from the address before the page's
698 * data arrives, so the menu is right from the first frame; the counts fill
699 * in once it does.
700 */
701type MenuRepo = {
702 namespace: string;
703 name: string;
704 member: boolean;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look705 /** Whether they see its settings; from the repository's page once it loads. */
706 settings?: boolean;
707 /** What they may do there, once the repository's page loads. */
708 can?: Abilities;
Sidebar: no settings flash on the way into a repository, and a better slide709 issues?: number;
710 pulls?: number;
711};
712
713function sameRepo(a: { namespace: string; name: string } | null, b: { namespace: string; name: string } | null) {
714 return (
715 a != null &&
716 b != null &&
717 a.namespace.toLowerCase() === b.namespace.toLowerCase() &&
718 a.name.toLowerCase() === b.name.toLowerCase()
719 );
720}
721
722/**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look723 * A project's own list, drilled into while you are in it: everything about
724 * the project, running and its code, and nothing else, with the way back
725 * out to all of them.
Sidebar: no settings flash on the way into a repository, and a better slide726 */
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put727function RepoMenu({
728 repo,
729 isPrivate,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look730 back,
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put731}: {
732 repo: MenuRepo;
733 isPrivate: boolean;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look734 /** Where the way back leads: the workspace's projects, mission control, or Explore. */
735 back: { to: string; label: string };
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put736}) {
Sidebar: no settings flash on the way into a repository, and a better slide737 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 put738 // 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 look739 const shows = new Set(projectPages(repo.member, repo.can));
Sidebar: no settings flash on the way into a repository, and a better slide740 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look741 <nav aria-label={`${repo.namespace}/${repo.name}`} className={PANEL}>
742 <BackRow to={back.to} label={back.label} />
Merge branch 'worktree-agent-ae1299e92e4462012'743 <Hint label="Overview" side="right">
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero744 <div>
A flat project menu with Code first, views as tabs, and Stripe for every owner745 <NavLink
Sidebar: no settings flash on the way into a repository, and a better slide746 to={base}
A flat project menu with Code first, views as tabs, and Stripe for every owner747 end
Fast pages, required checks on the branch, self-hosted runners, honest incidents748 prefetch="intent"
A flat project menu with Code first, views as tabs, and Stripe for every owner749 className={({ isActive }) =>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look750 `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 owner751 }
Sidebar: no settings flash on the way into a repository, and a better slide752 >
753 <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 page754 {isPrivate ? <Lock size={13} /> : <Box size={13} />}
Sidebar: no settings flash on the way into a repository, and a better slide755 </span>
756 <span className="min-w-0 truncate font-mono text-[0.8125rem]">
757 <span className="text-faint">{repo.namespace}/</span>
758 <span className="font-semibold text-fg">{repo.name}</span>
759 </span>
A flat project menu with Code first, views as tabs, and Stripe for every owner760 </NavLink>
Sidebar: soon rows and the project row keep their styles inside a hint; tiny amounts read as zero761 </div>
Merge branch 'worktree-agent-ae1299e92e4462012'762 </Hint>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look763 {/* A project's pages, in the order people use them. A page with more
764 than one view shows them as tabs across its top. */}
765 <Rule />
766 <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 request767 <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 owner768 Code
769 </SidebarLink>
Usage, Billing settings and prepaid AI credit; fixes from the UX audit770 <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 owner771 Issues
772 </SidebarLink>
773 <SidebarLink to={`${base}/pulls`} also={[`${base}/pull`, `${base}/queue`]} icon={<GitPullRequest size={15} />} count={repo.pulls}>
774 Pull requests
775 </SidebarLink>
Agents and memory, checks and conflicts, profiles, slug renames, custom domains776 <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 owner777 Agents
Agents and memory, checks and conflicts, profiles, slug renames, custom domains778 </SidebarLink>
A flat project menu with Code first, views as tabs, and Stripe for every owner779 <SidebarLink to={`${base}/actions`} icon={<PlayCircle size={15} />}>
780 Workflows
Projects: what a workspace builds and runs, first on every page781 </SidebarLink>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look782 </div>
783 <Rule />
784 <div className="space-y-px">
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put785 {shows.has("deployments") ? (
A flat project menu with Code first, views as tabs, and Stripe for every owner786 <SidebarLink to={`${base}/deployments`} also={soonPaths(base, "Deployments")} icon={<Rocket size={15} />}>
787 Deployments
788 </SidebarLink>
789 ) : null}
Observability gets its own page; tabs never overflow790 <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.">
791 Observability
A flat project menu with Code first, views as tabs, and Stripe for every owner792 </SidebarSoonLink>
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put793 {shows.has("security") ? (
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API794 <SidebarLink to={`${base}/security`} also={soonPaths(base, "Security")} icon={<ShieldCheck size={15} />}>
795 Security
796 </SidebarLink>
797 ) : null}
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97798 <SidebarLink
799 to={`${base}/contributors`}
800 also={[`${base}/activity`, `${base}/stargazers`, ...soonPaths(base, "Insights")]}
801 icon={<BarChart3 size={15} />}
802 >
A flat project menu with Code first, views as tabs, and Stripe for every owner803 Insights
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97804 </SidebarLink>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look805 </div>
806 {(repo.settings ?? shows.has("settings")) && (
807 <>
808 <Rule />
809 <SidebarLink to={`${base}/settings`} icon={<Settings size={15} />} drill>
A flat project menu with Code first, views as tabs, and Stripe for every owner810 Settings
811 </SidebarLink>
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look812 </>
813 )}
Sidebar: no settings flash on the way into a repository, and a better slide814 </nav>
815 );
816}
817
Project settings move into the sidebar, grouped, with a heading per page818/**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look819 * A project's settings, drilled into from its list: what is about running
820 * it, then its agents, then its code and who can reach it. The way back
821 * leads to the project.
Project settings move into the sidebar, grouped, with a heading per page822 */
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look823function RepoSettingsMenu({ repo }: { repo: MenuRepo }) {
Project settings move into the sidebar, grouped, with a heading per page824 const base = `/${repo.namespace}/${repo.name}`;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look825 // Each page shows to the roles that can use it, once the role is known.
826 const shows = (page: string) => !repo.can || repo.can[SETTINGS_CAPABILITY[page] ?? "administer"];
827 const running = shows("deployments");
828 const agents = shows("agents") || shows("guardrails");
Project settings move into the sidebar, grouped, with a heading per page829 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look830 <nav aria-label={`${repo.namespace}/${repo.name} settings`} className={PANEL}>
831 <BackRow to={base} label="Settings" context={`${repo.namespace}/${repo.name}`} />
832 {shows("") && (
833 <div className="mt-2 space-y-px">
834 <SidebarLink to={`${base}/settings`} end icon={<Settings size={15} />}>
835 General
836 </SidebarLink>
837 </div>
838 )}
839 {running && (
840 <>
841 {shows("") && <Rule />}
842 <div className={shows("") ? "space-y-px" : "mt-2 space-y-px"}>
843 <SidebarLink to={`${base}/settings/deployments`} icon={<Rocket size={15} />}>
844 Deployments
845 </SidebarLink>
846 <SidebarLink to={`${base}/settings/domains`} icon={<Globe size={15} />}>
847 Domains
848 </SidebarLink>
849 </div>
850 </>
851 )}
852 {agents && (
853 <>
854 <Rule />
855 <div className="space-y-px">
856 {shows("agents") && (
857 <SidebarLink to={`${base}/settings/agents`} icon={<Bot size={15} />}>
858 Agents
859 </SidebarLink>
860 )}
861 {shows("guardrails") && (
862 <SidebarLink to={`${base}/settings/guardrails`} icon={<ShieldCheck size={15} />}>
863 Guardrails
864 </SidebarLink>
865 )}
866 </div>
867 </>
868 )}
869 <Rule />
870 <div className="space-y-px">
871 {shows("repository") && (
872 <SidebarLink to={`${base}/settings/repository`} icon={<BookMarked size={15} />}>
873 Repository
874 </SidebarLink>
875 )}
Merge branch 'mirroring' into artifacts-mode876 {shows("mirroring") && (
877 <SidebarLink to={`${base}/settings/mirroring`} icon={<ArrowLeftRight size={15} />}>
878 Mirroring
879 </SidebarLink>
880 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look881 {shows("access") && (
882 <SidebarLink to={`${base}/settings/access`} icon={<Users size={15} />}>
883 Access
884 </SidebarLink>
885 )}
Merge branch 'worktree-agent-a5a5de74d8863d554' into worktree-agent-a16631325aecf58ca886 {shows("keys") && (
887 <SidebarLink to={`${base}/settings/keys`} icon={<KeyRound size={15} />}>
888 Deploy keys
889 </SidebarLink>
890 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look891 {shows("branches") && (
892 <SidebarLink to={`${base}/settings/branches`} icon={<GitBranch size={15} />}>
893 Branches and merging
894 </SidebarLink>
895 )}
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge896 {shows("rules") && (
897 <SidebarLink to={`${base}/settings/rules`} icon={<Scale size={15} />}>
898 Rules
899 </SidebarLink>
900 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look901 {shows("secrets") && (
902 <SidebarLink to={`${base}/settings/secrets`} icon={<Lock size={15} />}>
903 Secrets and variables
904 </SidebarLink>
905 )}
Merge branch 'worktree-agent-a3abfcce648e87dca'906 {shows("actions") && (
907 <SidebarLink to={`${base}/settings/actions`} icon={<PlayCircle size={15} />}>
908 Actions
909 </SidebarLink>
910 )}
911 {shows("environments") && (
912 <SidebarLink to={`${base}/settings/environments`} icon={<Layers size={15} />}>
913 Environments
914 </SidebarLink>
915 )}
Fast pages, required checks on the branch, self-hosted runners, honest incidents916 {shows("runners") && (
917 <SidebarLink to={`${base}/settings/runners`} icon={<ServerCog size={15} />}>
918 Runners
919 </SidebarLink>
920 )}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look921 {shows("webhooks") && (
922 <SidebarLink to={`${base}/settings/webhooks`} icon={<Webhook size={15} />}>
923 Webhooks
924 </SidebarLink>
925 )}
926 </div>
Project settings move into the sidebar, grouped, with a heading per page927 </nav>
928 );
929}
930
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)931/**
932 * Whether the menus list Settings → Invites (invites to g1t): always while
933 * sign-up takes an invite; once anyone can sign up, only for someone with
934 * invites already made to look back on, which the account menu's data says.
935 */
936function useInvitesListed(): boolean {
937 const inviteOnly = useInviteOnly();
938 const details = useFetcher<AccountMenuData | null>({ key: "account-menu" });
939 useEffect(() => {
940 if (!inviteOnly && details.state === "idle" && details.data === undefined) details.load("/settings/menu.json");
941 // eslint-disable-next-line react-hooks/exhaustive-deps
942 }, [inviteOnly]);
943 return inviteOnly || details.data?.invites_page === true;
944}
945
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas946/** Your own settings, drilled into from Your settings: one page each. */
947function 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)948 const invites = useInvitesListed();
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas949 const link = (page: AccountSettingsPage, icon: ReactNode) => (
950 <SidebarLink to={`/settings/${page}`} icon={icon}>
951 {ACCOUNT_SETTINGS[page].title}
952 </SidebarLink>
Sidebar: no settings flash on the way into a repository, and a better slide953 );
954 return (
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look955 <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 quotas956 <BackRow to="/" label="Your settings" context={username} />
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look957 <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 quotas958 {link("profile", <CircleUserRound size={15} />)}
959 {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)960 {invites && link("invites", <Ticket size={15} />)}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas961 </div>
962 <Rule />
963 <div className="space-y-px">
964 {link("keys", <Fingerprint size={15} />)}
965 {link("tokens", <KeyRound size={15} />)}
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look966 </div>
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas967 <Rule />
968 <div className="space-y-px">
Integrations are a directory of connectors, for a workspace and for each person969 {link("integrations", <Blocks size={15} />)}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas970 {link("github", <GithubMark className="size-[15px]" />)}
971 {link("applications", <Plug size={15} />)}
972 </div>
973 <Rule />
974 <div className="space-y-px">
Merge main (membership, two-factor, GitHub repo roles) into tokens975 {link("two-factor", <ShieldCheck size={15} />)}
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas976 {link("security-log", <History size={15} />)}
977 </div>
Sidebar: no settings flash on the way into a repository, and a better slide978 </nav>
979 );
980}
981
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put982/**
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.983 * Code's sidebar: its Overview, the projects, what spans them and what is
984 * coming; in a project, drilled into the project's own list, and its
985 * settings one level further in. The address says which, so a link
986 * 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 put987 */
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.988function CodeSidebar({
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look989 user,
990 shell,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas991 missing = false,
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look992}: {
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.993 user: User;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look994 shell: ShellData;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas995 /** The page is a 404: the address names nothing the viewer can see. */
996 missing?: boolean;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look997}) {
Sidebar: no settings flash on the way into a repository, and a better slide998 const ws = shell.workspace;
999 const { pathname } = useLocation();
1000 const going = useNavigation().location?.pathname;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1001 // Where the sidebar is drilled to follows the page being gone to, so it
1002 // moves as the link is followed, not once the page arrives.
1003 const target = going ?? pathname;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1004 // On a 404, the address is not a place: no list is drilled into from it,
1005 // except the project's own when the project is real and visible and only
1006 // something inside it is missing (a file, a commit, an issue).
1007 const lost = missing && going == null;
Sidebar: no settings flash on the way into a repository, and a better slide1008 const active = shell.repo;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1009 // In a repository, or on the way into one, its own list.
Sidebar: no settings flash on the way into a repository, and a better slide1010 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.1011 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 look1012 // An invitation to a repository is answered before its menu means anything.
1013 const inRepo =
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1014 repoPath != null &&
1015 !reserved.has(repoPath[1]) &&
1016 repoPath[2] !== "-" &&
1017 !/^\/[^/]+\/[^/]+\/invitations\/?$/.test(target) &&
1018 (!lost || sameRepo(active, { namespace: repoPath[1]!, name: repoPath[2]! }));
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1019 // A project's settings, one level further in.
Project settings move into the sidebar, grouped, with a heading per page1020 const inRepoSettings = inRepo && REPO_SETTINGS_PAGE.test(target);
Sidebar: no settings flash on the way into a repository, and a better slide1021 // The repository the menu is for: the one loaded if it is the one being
1022 // gone to, else what the address says, at once.
1023 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 look1024 const guessed: MenuRepo | null = targetRepo
Sidebar: no settings flash on the way into a repository, and a better slide1025 ? sameRepo(active, targetRepo)
1026 ? active
1027 : {
1028 ...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.1029 member: (user.workspaces ?? []).some((m) => m.slug === targetRepo.namespace.toLowerCase()),
Sidebar: no settings flash on the way into a repository, and a better slide1030 }
1031 : null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1032 // The viewer's role there, from the repository's page once it has loaded.
1033 const page = useRouteLoaderData("routes/repo/layout") as
1034 | { repo?: { namespace: string; name: string }; access?: ViewerAccess }
1035 | undefined;
1036 const menuRepo: MenuRepo | null =
1037 guessed && page?.access && page.repo && sameRepo(page.repo, guessed)
1038 ? { ...guessed, member: page.access.insider, settings: seesSettings(page.access), can: page.access.can }
1039 : guessed;
1040
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.1041 // The way from Code's list to the one shown.
1042 const trail: Level[] = [{ key: "main", node: ws ? <CodeMenu shell={shell} slug={ws.slug} /> : null }];
1043 if (menuRepo) {
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1044 const key = `repo:${menuRepo.namespace}/${menuRepo.name}`.toLowerCase();
1045 // 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.1046 const home = (user.workspaces ?? []).find((m) => m.slug === menuRepo.namespace.toLowerCase());
1047 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 look1048 trail.push({
1049 key,
1050 node: (
1051 <RepoMenu
1052 repo={menuRepo}
1053 isPrivate={[...shell.repos, ...(shell.shared ?? [])].some((repo) => sameRepo(repo, menuRepo) && repo.isPrivate)}
1054 back={back}
1055 />
1056 ),
1057 });
1058 if (inRepoSettings) trail.push({ key: `${key}:settings`, node: <RepoSettingsMenu repo={menuRepo} /> });
1059 }
1060
Sidebar: no settings flash on the way into a repository, and a better slide1061 return (
1062 <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.1063 <ModeHeader title="Code" />
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1064 <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)1065 </div>
1066 );
1067}
1068
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.1069/**
1070 * A mode's sidebar heading: its name, quiet, under the workspace's
1071 * switcher, with what it makes at the end.
1072 */
1073export 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)1074 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.1075 <div className="flex h-9 shrink-0 items-center gap-1 pr-1 pl-3">
1076 <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)1077 {action}
1078 </div>
1079 );
1080}
1081
1082/**
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 * 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)1084 * 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.1085 * 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)1086 * agents, context and memory are Agents'.
1087 */
1088function CodeMenu({ shell, slug }: { shell: ShellData; slug: string }) {
1089 const { pathname } = useLocation();
1090 const going = useNavigation().location?.pathname;
1091 const path = going ?? pathname;
1092 const at = (page: string) => path === `/${slug}/-/${page}` || path.startsWith(`/${slug}/-/${page}/`);
1093 const shared = shell.shared ?? [];
1094 return (
1095 <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.1096 <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)1097 <SidebarLink to={`/${slug}/-/overview`} icon={<LayoutDashboard size={15} />} current={at("overview")}>
1098 Overview
1099 </SidebarLink>
1100 </div>
1101 <div className="mt-3">
1102 <SidebarProjects slug={slug} shell={shell} current={at("projects")} />
1103 </div>
1104 <Rule />
1105 <div className="space-y-px">
1106 <SidebarLink to={`/${slug}/-/security`} icon={<ShieldCheck size={15} />} current={at("security") && !at("security/settings")}>
1107 Security
1108 </SidebarLink>
1109 <SidebarLink to={`/${slug}/-/packages`} icon={<Package size={15} />} current={at("packages")}>
1110 Packages
1111 </SidebarLink>
1112 {INSIGHTS && (
1113 <SidebarSoonLink to={`/${slug}/-/insights`} icon={<TrendingUp size={15} />} about={INSIGHTS.summary} current={at("insights")}>
1114 {INSIGHTS.title}
1115 </SidebarSoonLink>
1116 )}
1117 {roadmapIn("Workspace")
1118 .filter((item) => item.key !== "insights" && item.key !== "teams" && item.key !== "fleet")
1119 .map((item) => (
1120 <SidebarSoonLink key={item.key} to={`/${slug}/-/soon/${item.key}`} icon={WORKSPACE_ICONS[item.key] ?? <Sparkles size={15} />} about={item.summary}>
1121 {item.title === "Board" ? "Boards" : item.title}
1122 </SidebarSoonLink>
1123 ))}
1124 </div>
1125 {shared.length > 0 && (
1126 <>
1127 <Rule />
1128 <SidebarGroup title="Shared with you">
1129 {shared.map((repo) => (
1130 <SidebarLink
1131 key={`${repo.namespace}/${repo.name}`}
1132 to={`/${repo.namespace}/${repo.name}`}
1133 icon={repo.isPrivate ? <Lock size={15} /> : <Box size={15} />}
1134 drill="hover"
1135 >
1136 <span className="font-mono text-faint">{repo.namespace}/</span>
1137 {repo.name}
1138 </SidebarLink>
1139 ))}
1140 </SidebarGroup>
1141 </>
1142 )}
1143 </nav>
1144 );
1145}
1146
1147/** Workspace pages that sit in its Settings list, drilled into from the Workspace sidebar. */
The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how.1148const WORKSPACE_SETTINGS = ["settings", "repositories", "tokens", "personal-access-tokens", "secrets", "actions", "webhooks", "emoji"];
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)1149
1150/**
1151 * The Workspace mode's sidebar: the workspace itself, for every member.
The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how.1152 * Its overview, money, machines, 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)1153 * settings as a list of their own. Owner-only pages stay owner-only.
1154 */
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.1155export 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)1156 const { pathname } = useLocation();
1157 const going = useNavigation().location?.pathname;
1158 const path = going ?? pathname;
1159 const page = path.startsWith(`/${slug}/-/`) ? path.slice(`/${slug}/-/`.length) : "";
1160 const top = page.split("/")[0] ?? "";
1161 const at = (...pages: string[]) => pages.some((p) => page === p || page.startsWith(`${p}/`));
1162 const inSettings = WORKSPACE_SETTINGS.includes(top);
1163 const main = (
1164 <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.1165 <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)1166 <SidebarLink to={`/${slug}/-/workspace`} icon={<LayoutGrid size={15} />} current={at("workspace")}>
1167 Overview
1168 </SidebarLink>
1169 </div>
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.1170 <SidebarGroup title="Money" className="mt-3">
1171 <SidebarLink to={`/${slug}/-/spend`} icon={<Coins size={15} />} current={at("spend")}>
1172 Spend
1173 </SidebarLink>
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.1174 <SidebarLink to={`/${slug}/-/usage`} icon={<BarChart3 size={15} />} current={at("usage")}>
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)1175 Usage
1176 </SidebarLink>
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.1177 <SidebarLink to={`/${slug}/-/gateway`} icon={<Network size={15} />} current={at("gateway")}>
1178 AI Gateway
1179 </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)1180 <SidebarLink to={`/${slug}/-/billing`} icon={<CreditCard size={15} />} current={at("billing")}>
1181 Billing and plans
1182 </SidebarLink>
1183 </SidebarGroup>
The Runners page shows the machines a workspace's agents and workflow jobs run on, in Workspace under Compute: g1t's cloud beside your own runners, what each is running now with a link to it, what's waiting, this month's machine time and its cost (your own runners' free), where agent work and workflow jobs run, adding a runner, and groups; runner_activity in Actions says what runs where, work handed to your runners keeps its agent run, and the self-hosted runners guide says how.1184 {owner && (
1185 <SidebarGroup title="Compute" className="mt-3">
1186 <SidebarLink to={`/${slug}/-/runners`} icon={<ServerCog size={15} />} current={at("runners")}>
1187 Runners
1188 </SidebarLink>
1189 </SidebarGroup>
1190 )}
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)1191 <SidebarGroup title="Connections" className="mt-3">
1192 <SidebarLink to={`/${slug}/-/integrations`} icon={<Plug size={15} />} current={at("integrations")}>
1193 Integrations
1194 </SidebarLink>
1195 </SidebarGroup>
1196 <SidebarGroup title="Security policies" className="mt-3">
1197 <SidebarLink to={`/${slug}/-/security/settings`} icon={<ShieldCheck size={15} />} current={at("security/settings")}>
1198 Security settings
1199 </SidebarLink>
1200 <SidebarLink to={`/${slug}/-/guardrails`} icon={<Gauge size={15} />} current={at("guardrails")}>
1201 Guardrails
1202 </SidebarLink>
1203 <SidebarLink to={`/${slug}/-/rules`} icon={<Scale size={15} />} current={at("rules")}>
1204 Rules
1205 </SidebarLink>
1206 </SidebarGroup>
1207 <Rule />
1208 <div className="space-y-px">
1209 <SidebarLink to={`/${slug}/-/audit`} icon={<History size={15} />} current={at("audit")}>
1210 Audit log
1211 </SidebarLink>
1212 <SidebarLink to={owner ? `/${slug}/-/settings` : `/${slug}/-/repositories`} icon={<Settings size={15} />} drill current={inSettings}>
1213 Settings
1214 </SidebarLink>
1215 </div>
1216 </nav>
1217 );
1218 const settings = (
1219 <nav aria-label="Workspace settings" className={PANEL}>
1220 <BackRow to={`/${slug}/-/workspace`} label="Settings" context={slug} />
1221 <div className="mt-2 space-y-px">
1222 {owner && (
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1223 <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)1224 General
1225 </SidebarLink>
1226 )}
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1227 <SidebarLink to={`/${slug}/-/settings/chat`} icon={<MessagesSquare size={15} />}>
1228 Chat
1229 </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)1230 <SidebarLink to={`/${slug}/-/repositories`} icon={<BookMarked size={15} />}>
1231 Repositories
1232 </SidebarLink>
1233 <SidebarLink to={`/${slug}/-/tokens`} icon={<KeyRound size={15} />}>
1234 Access tokens
1235 </SidebarLink>
1236 {owner && (
1237 <SidebarLink to={`/${slug}/-/personal-access-tokens`} icon={<UserRoundKey size={15} />}>
1238 Personal access tokens
1239 </SidebarLink>
1240 )}
1241 <SidebarLink to={`/${slug}/-/webhooks`} icon={<Webhook size={15} />}>
1242 Webhooks
1243 </SidebarLink>
1244 <SidebarLink to={`/${slug}/-/emoji`} icon={<Smile size={15} />}>
1245 Emoji
1246 </SidebarLink>
1247 </div>
1248 <SidebarGroup title="Runs" className="mt-3">
1249 <SidebarLink to={`/${slug}/-/secrets`} icon={<Lock size={15} />}>
1250 Secrets and variables
1251 </SidebarLink>
1252 <SidebarLink to={`/${slug}/-/actions`} icon={<PlayCircle size={15} />}>
1253 Actions
1254 </SidebarLink>
1255 </SidebarGroup>
1256 </nav>
1257 );
1258 const trail: Level[] = [{ key: "workspace", node: main }];
1259 if (inSettings) trail.push({ key: "workspace:settings", node: settings });
1260 return (
1261 <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.1262 <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)1263 <Drill trail={trail} />
1264 </div>
1265 );
1266}
1267
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.1268/**
1269 * People's sidebar: everyone in the workspace, people and agents; its
1270 * teams; the org chart; and, to manage who belongs, members and invites.
1271 */
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.1272function PeopleSidebar({ slug }: { slug: string }) {
1273 const { pathname } = useLocation();
1274 const going = useNavigation().location?.pathname;
1275 const path = going ?? pathname;
1276 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)1277 return (
1278 <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.1279 <ModeHeader title="People" />
1280 <nav aria-label="People" className={PANEL}>
1281 <div className="space-y-px">
1282 <SidebarLink to={`/${slug}/-/people`} icon={<Users size={15} />} current={at("people")}>
1283 Everyone
1284 </SidebarLink>
1285 <SidebarLink to={`/${slug}/-/teams`} icon={<UsersRound size={15} />} current={at("teams")}>
1286 Teams
1287 </SidebarLink>
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.1288 <SidebarLink to={`/${slug}/-/org-chart`} icon={<Network size={15} />} current={at("org-chart")}>
1289 Org chart
1290 </SidebarLink>
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.1291 </div>
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.1292 <SidebarGroup title="Membership" className="mt-3">
1293 <SidebarLink to={`/${slug}/-/members`} icon={<UserPlus size={15} />} current={at("members")}>
1294 Members and invites
1295 </SidebarLink>
1296 </SidebarGroup>
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.1297 </nav>
1298 </div>
1299 );
1300}
1301
1302/**
1303 * Notifications' sidebar: what you have not finished with, what you saved
1304 * and what is done; then why you were told, which narrows any of them.
1305 */
1306function NotificationsSidebar({ counts }: { counts: InboxCounts | null }) {
1307 const { search } = useLocation();
1308 const params = new URLSearchParams(search);
1309 const view = inboxView(params.get("view"));
1310 const reason = inboxReason(params.get("reason"));
1311 const tab = params.get("tab");
1312 const address = (changes: Record<string, string | null>) => {
1313 const merged: Record<string, string | null> = { tab, view: view === "inbox" ? null : view, reason, ...changes };
1314 const next = new URLSearchParams();
1315 for (const [name, value] of Object.entries(merged)) if (value) next.set(name, value);
1316 const query = next.toString();
1317 return query ? `/notifications?${query}` : "/notifications";
1318 };
1319 const views = [
1320 { view: "inbox", label: "Everything", icon: <Bell size={15} />, count: counts?.unread },
1321 { view: "saved", label: "Saved", icon: <Bookmark size={15} /> },
1322 { view: "done", label: "Done", icon: <Check size={15} /> },
1323 ] as const;
1324 return (
1325 <div className="flex h-full flex-col">
1326 <ModeHeader title="Notifications" />
1327 <nav aria-label="Notifications" className={PANEL}>
1328 <div className="space-y-px">
1329 {views.map((entry) => (
1330 <SidebarLink
1331 key={entry.view}
1332 to={address({ view: entry.view === "inbox" ? null : entry.view, before: null })}
1333 icon={entry.icon}
1334 count={"count" in entry ? (entry.count ?? undefined) : undefined}
1335 current={view === entry.view}
1336 >
1337 {entry.label}
1338 </SidebarLink>
1339 ))}
1340 </div>
1341 <SidebarGroup title="Why you were told" className="mt-4">
1342 {REASON_FILTERS.map((entry) => (
1343 <SidebarLink
1344 key={entry.reason ?? "any"}
1345 to={address({ reason: entry.reason, before: null })}
1346 icon={<span className="block size-[15px]" />}
1347 current={reason === entry.reason}
1348 >
1349 {entry.reason == null ? "Any reason" : entry.label}
1350 </SidebarLink>
1351 ))}
1352 </SidebarGroup>
1353 </nav>
1354 </div>
1355 );
1356}
1357
1358/** Your own settings, beside the page: under the account menu, not any workspace's. */
1359export function AccountSidebar({ username }: { username: string }) {
1360 return (
1361 <div className="flex h-full flex-col">
1362 <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)1363 <div className="min-h-0 grow">
1364 <AccountSettingsMenu username={username} />
Sidebar: no settings flash on the way into a repository, and a better slide1365 </div>
1366 </div>
1367 );
1368}
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)1369
Sidebar: no settings flash on the way into a repository, and a better slide1370/** Words for the sections a path can end in. */
1371const SECTIONS: Record<string, string> = {
1372 issues: "Issues",
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1373 milestones: "Milestones",
1374 labels: "Labels",
Sidebar: no settings flash on the way into a repository, and a better slide1375 pulls: "Pull requests",
1376 queue: "Merge queue",
1377 commits: "Commits",
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales1378 plans: "Outcomes",
1379 actions: "Workflows",
1380 soon: "Soon",
Deployments: a preview for every pull request, production on g1t.page1381 deployments: "Deployments",
Projects: what a workspace builds and runs, first on every page1382 repository: "Repository",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1383 access: "Access",
1384 invitations: "Invitation",
1385 repositories: "Repositories",
Branches and Tags pages, each file's last commit, and the branch menu on files1386 branches: "Branches",
1387 tags: "Tags",
Compare: any two branches, the commits one has that the other does not, and the diff, with Open a pull request1388 compare: "Compare",
A menu shaped by how g1t works, Soon pages for every promise, and sudo for sales1389 code: "Files",
Sidebar: no settings flash on the way into a repository, and a better slide1390 secrets: "Secrets and variables",
1391 settings: "Settings",
Navigation: the workspace's own page with tabs, pins and recent in the sidebar1392 people: "People",
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.1393 "org-chart": "Org chart",
1394 members: "Members and invites",
Navigation: the workspace's own page with tabs, pins and recent in the sidebar1395 projects: "Projects",
1396 teams: "Teams",
Sidebar: no settings flash on the way into a repository, and a better slide1397 tokens: "Access tokens",
Settings: fine-grained tokens, workspace token Admin, workspace personal access token rules1398 "personal-access-tokens": "Personal access tokens",
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.1399 spend: "Spend",
1400 receipts: "Receipts",
Sidebar: no settings flash on the way into a repository, and a better slide1401 usage: "Usage",
Site: the AI Gateway page's breadcrumb reads "AI Gateway"1402 gateway: "AI Gateway",
Secrets and variables: one list, rows per environment, for workflows and deployments1403 billing: "Billing and plans",
Sidebar: no settings flash on the way into a repository, and a better slide1404 integrations: "Integrations",
1405 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)1406 emoji: "Emoji",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1407 domains: "Domains",
1408 guardrails: "Guardrails",
Merge rulesets: branch and tag rules, agent-first, enforced on push and merge1409 rules: "Rules",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1410 audit: "Audit log",
Files pages say Files in the trail and keep the description in About only1411 tree: "Files",
1412 blob: "Files",
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail1413 agents: "Agents",
1414 context: "Context",
1415 memory: "Memory",
1416 security: "Security",
1417 packages: "Packages",
1418 runners: "Runners",
Merge branch 'worktree-agent-a3abfcce648e87dca'1419 environments: "Environments",
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail1420 workflows: "Workflows",
1421 observability: "Observability",
1422 insights: "Insights",
1423 sessions: "Sessions",
Chat and workspace agents: channels, DMs and named agents you talk to1424 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.1425 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.1426 today: "Today",
1427 apps: "Apps",
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.1428 marketplace: "Marketplace",
Chat and workspace agents: channels, DMs and named agents you talk to1429 "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)1430 overview: "Overview",
1431 workspace: "Workspace",
Sidebar: no settings flash on the way into a repository, and a better slide1432};
1433
Merge branch 'worktree-agent-a3abfcce648e87dca'1434/** Settings pages whose name differs from the section's of the same word. */
1435const SETTINGS_SECTIONS: Record<string, string> = { branches: "Branches and merging", actions: "Actions" };
1436
Sidebar: no settings flash on the way into a repository, and a better slide1437/** 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.1438function Breadcrumbs({
1439 pathname,
1440 missing,
1441 repo,
1442 workspace,
1443}: {
1444 pathname: string;
1445 missing?: boolean;
1446 repo?: ShellData["repo"];
1447 /** The workspace you are in: the switcher names it, so the trail starts after it. */
1448 workspace: string | null;
1449}) {
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1450 // A 404 names nothing from the address, unless the project is real and
1451 // visible and only something inside it is missing.
1452 const visibleRepo = /^\/([^/]+)\/([^/-][^/]*)(\/|$)/.exec(pathname);
1453 if (missing && !(visibleRepo && sameRepo(repo ?? null, { namespace: visibleRepo[1]!, name: visibleRepo[2]! }))) {
1454 return <span className="text-sm font-medium">Not found</span>;
1455 }
Sidebar: no settings flash on the way into a repository, and a better slide1456 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.1457 const reserved = ["settings", "explore", "new", "search", "workspaces", "policies", "security", "support", "status", "invite", "notifications"];
1458 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 quotas1459 // Your settings: Settings / Emails.
1460 if (parts[0] === "settings") {
1461 const page = accountSettingsPage(pathname);
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1462 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 quotas1463 }
Sidebar: no settings flash on the way into a repository, and a better slide1464 if (reserved.includes(parts[0]!)) {
1465 const words: Record<string, string> = {
1466 settings: "Account",
1467 explore: "Explore",
Projects live: fixes from walking them end to end1468 new: "New project",
Sidebar: no settings flash on the way into a repository, and a better slide1469 search: "Search",
1470 workspaces: "New workspace",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1471 policies: "Policies",
1472 security: "Security",
1473 support: "Support",
1474 status: "Status",
1475 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.1476 notifications: "Notifications",
Sidebar: no settings flash on the way into a repository, and a better slide1477 };
1478 return <span className="text-sm font-medium">{words[parts[0]!]}</span>;
1479 }
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put1480 // A person's profile, by their handle.
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1481 if (parts[0] === "u" && parts[1]) return <ProfileCrumb username={parts[1]} />;
Sidebar: no settings flash on the way into a repository, and a better slide1482 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.1483 const ours = workspace != null && owner!.toLowerCase() === workspace.toLowerCase();
1484 const trail: Crumb[] = ours ? [] : [{ label: owner!, to: `/${owner}`, mono: true }];
Sidebar: no settings flash on the way into a repository, and a better slide1485 if (second === "-") {
1486 const page = `/${owner}/-/${third}`;
1487 if (third && SETTINGS_PAGE.test(page)) {
1488 trail.push({ label: "Settings", to: `/${owner}/-/settings` });
1489 trail.push({ label: third === "settings" ? "General" : (SECTIONS[third] ?? third), to: page });
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.1490 } else if (third) {
1491 trail.push({ label: SECTIONS[third] ?? third, to: page });
The Marketplace adds what g1t doesn't do and connects what you already use: extensions (Mail, Support, CRM, Recruiting, On-call, and bridges to a helpdesk, CRM or ERP you run, all Soon), starter kits, and integrations connected by the workspace or by each person; agents aren't installed there. Agent templates live in Agents, as starting points you configure, at Agents → Templates, and the Marketplace's old agent addresses lead there. The marketplace and agents guides say how.1492 // The Marketplace names its tab (Marketplace / Extensions), and Agents its templates.
1493 const tabs: Record<string, string> =
1494 third === "marketplace" ? { integrations: "Integrations", extensions: "Extensions", requests: "Requests" } : third === "agents" ? { templates: "Templates" } : {};
1495 const tab = fourth ? tabs[fourth] : undefined;
The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how.1496 if (tab) trail.push({ label: tab, to: `${page}/${fourth}` });
1497 }
Sidebar: no settings flash on the way into a repository, and a better slide1498 } else if (second) {
1499 const repo = `/${owner}/${second}`;
1500 trail.push({ label: second, to: repo, mono: true });
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1501 if (third === "pull" && fourth) trail.push({ label: `Pull request #${fourth}`, short: `#${fourth}`, to: `${repo}/pull/${fourth}` });
1502 else if (third === "issues" && fourth && fourth !== "new") trail.push({ label: `Issue #${fourth}`, short: `#${fourth}`, to: `${repo}/issues/${fourth}` });
Sidebar: no settings flash on the way into a repository, and a better slide1503 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 deployments1504 else if (third && SECTIONS[third]) {
1505 trail.push({ label: SECTIONS[third]!, to: `${repo}/${third}` });
1506 // A settings page names which one: Settings / Secrets and variables.
1507 if (third === "settings" && fourth && SECTIONS[fourth]) {
Merge branch 'worktree-agent-a3abfcce648e87dca'1508 trail.push({ label: SETTINGS_SECTIONS[fourth] ?? SECTIONS[fourth]!, to: `${repo}/settings/${fourth}` });
Secrets and variables: one list, rows per environment, for workflows and deployments1509 }
1510 }
Sidebar: no settings flash on the way into a repository, and a better slide1511 }
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.1512 if (trail.length === 0) trail.push({ label: "Overview", to: `/${owner}` });
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1513 return <Trail trail={trail} />;
1514}
1515
Chat controls, public profiles, shadcn selects, and no Docs tab in a project1516/** A profile's place in the top bar: the person's avatar and @handle, from the page once it has loaded. */
1517function 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 managers1518 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 project1519 const profile = page?.profile?.username.toLowerCase() === username.toLowerCase() ? page.profile : null;
1520 return (
1521 <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">
1522 <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 managers1523 <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 project1524 </Link>
1525 );
1526}
1527
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1528/** One link of the trail; `short` is what a phone shows when it is the page itself. */
1529type Crumb = { label: string; to: string; mono?: boolean; short?: string };
1530
1531/**
1532 * The trail of links. On a phone there is room for one: the page itself,
1533 * with a way back to where it sits; the whole trail from a wider screen up.
1534 */
1535function 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)1536 // Up on a phone, unless up is the workspace itself: its pages are the tabs.
1537 const up = trail.length > 1 && !/^\/[^/]+$/.test(trail[trail.length - 2]!.to) ? trail[trail.length - 2]! : null;
Sidebar: no settings flash on the way into a repository, and a better slide1538 return (
1539 <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 audit1540 {up && (
1541 <Link
1542 to={up.to}
1543 prefetch="intent"
1544 aria-label={`Back to ${up.label}`}
1545 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"
1546 >
1547 <ChevronLeft size={16} />
1548 </Link>
1549 )}
1550 {trail.map((crumb, index) => {
1551 const last = index === trail.length - 1;
1552 return (
1553 <span key={index} className={`min-w-0 items-center gap-1.5 ${last ? "flex" : "hidden sm:flex"}`}>
1554 {index > 0 && <span className="hidden text-line-strong sm:inline">/</span>}
1555 <Link
1556 to={crumb.to}
1557 prefetch="intent"
1558 aria-current={last ? "page" : undefined}
1559 className={`truncate rounded px-1 py-0.5 transition-colors hover:bg-raised ${
1560 last ? "font-medium text-fg" : "text-muted hover:text-fg"
1561 } ${crumb.mono ? "font-mono text-[0.8125rem]" : ""}`}
1562 >
1563 {last && crumb.short ? (
1564 <>
1565 <span className="sm:hidden">{crumb.short}</span>
1566 <span className="hidden sm:inline">{crumb.label}</span>
1567 </>
1568 ) : (
1569 crumb.label
1570 )}
1571 </Link>
1572 </span>
1573 );
1574 })}
Sidebar: no settings flash on the way into a repository, and a better slide1575 </nav>
1576 );
1577}
1578
Search across all of g1t, Explore, and a command palette1579type Command = PaletteCommand;
Sidebar: no settings flash on the way into a repository, and a better slide1580
1581/** 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.1582function commandsFor(user: User, shell: ShellData): Command[] {
1583 const ws = shell.workspace;
Sidebar: no settings flash on the way into a repository, and a better slide1584 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.1585 ...(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)1586 ? [
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.1587 { label: "Today", to: todayPath(ws.slug), icon: <Sun size={15} /> },
1588 { label: "Chat", to: `/${ws.slug}/-/chat`, icon: <MessagesSquare size={15} /> },
1589 { label: "Agents", to: `/${ws.slug}/-/agents`, icon: <Sparkles size={15} /> },
1590 ...(hasCodeAccess(ws) ? [{ label: "Code overview", to: `/${ws.slug}/-/overview`, icon: <Code2 size={15} /> }] : []),
1591 { label: "Artifacts", to: `/${ws.slug}/-/artifacts`, icon: <Shapes size={15} /> },
1592 { label: "Apps", hint: "Everything installed that you can use", to: `/${ws.slug}/-/apps`, icon: <LayoutGrid size={15} /> },
The Marketplace adds what g1t doesn't do and connects what you already use: extensions (Mail, Support, CRM, Recruiting, On-call, and bridges to a helpdesk, CRM or ERP you run, all Soon), starter kits, and integrations connected by the workspace or by each person; agents aren't installed there. Agent templates live in Agents, as starting points you configure, at Agents → Templates, and the Marketplace's old agent addresses lead there. The marketplace and agents guides say how.1593 { label: "Marketplace", hint: "Extensions and integrations to add", to: `/${ws.slug}/-/marketplace`, icon: <Store size={15} /> },
1594 { label: "Agent templates", hint: "Starting points for a new agent", to: `/${ws.slug}/-/agents/templates`, icon: <Bot 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.1595 { 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)1596 ]
1597 : []),
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step1598 ...(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-agent1599 ? [{ 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 step1600 : []),
Sidebar: no settings flash on the way into a repository, and a better slide1601 { label: "Explore repositories", to: "/explore", icon: <Compass size={15} /> },
Search across all of g1t, Explore, and a command palette1602 { 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.1603 { label: "Notifications", hint: "What needs you", to: "/notifications", icon: <Bell size={15} /> },
Projects: what a workspace builds and runs, first on every page1604 { label: "New project", to: "/new", icon: <Plus size={15} /> },
Sidebar: no settings flash on the way into a repository, and a better slide1605 { 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 quotas1606 { label: "Your settings", to: FIRST_SETTINGS_PAGE, icon: <Settings size={15} /> },
1607 ...(Object.keys(ACCOUNT_SETTINGS) as AccountSettingsPage[])
1608 .filter((page) => page !== "profile")
1609 .map((page) => ({ label: ACCOUNT_SETTINGS[page].title, hint: "Your settings", to: `/settings/${page}`, icon: <Settings size={15} /> })),
You choose how g1t looks: Auto follows your system, Light and Dark stay put, set from the account menu, the phone's You and help sheet, Settings → Account or the command palette; the page is drawn in your choice from the first byte, every colour has a light value that reads at 4.5:1 or better, code and diffs are highlighted for both, diagrams and the document editor follow along, the product tour and the g1t mark's avatar stay dark, and Dark is what you see until you choose; the workspaces guide says how.1610 ...THEME_COMMANDS,
Sidebar: no settings flash on the way into a repository, and a better slide1611 ];
1612 const repo = shell.repo;
1613 if (repo) {
1614 const base = `/${repo.namespace}/${repo.name}`;
1615 const name = `${repo.namespace}/${repo.name}`;
1616 commands.unshift(
Projects: what a workspace builds and runs, first on every page1617 { label: "Overview", hint: name, to: base, icon: <LayoutGrid size={15} /> },
1618 { label: "Code", hint: name, to: `${base}/code`, icon: <Code2 size={15} /> },
Sidebar: no settings flash on the way into a repository, and a better slide1619 { label: "Issues", hint: name, to: `${base}/issues`, icon: <CircleDot size={15} /> },
1620 { 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 step1621 ...(repo.member
1622 ? [{ label: `Put an agent on ${repo.name}`, hint: name, to: `${base}/issues/new?agent=1`, icon: <Sparkles size={15} /> }]
1623 : []),
Sidebar: no settings flash on the way into a repository, and a better slide1624 { label: "Pull requests", hint: name, to: `${base}/pulls`, icon: <GitPullRequest size={15} /> },
1625 { label: "Commits", hint: name, to: `${base}/commits`, icon: <History size={15} /> },
1626 ...(repo.member
1627 ? [
1628 { label: "Plan work", hint: name, to: `${base}/plans`, icon: <ListTree size={15} /> },
Projects: what a workspace builds and runs, first on every page1629 { label: "Deployments", hint: name, to: `${base}/deployments`, icon: <Rocket size={15} /> },
1630 { label: "Secrets and variables", hint: name, to: `${base}/settings/secrets`, icon: <Lock size={15} /> },
1631 { label: "Project settings", hint: name, to: `${base}/settings`, icon: <Settings size={15} /> },
1632 { label: "Repository settings", hint: name, to: `${base}/settings/repository`, icon: <Settings size={15} /> },
Sidebar: no settings flash on the way into a repository, and a better slide1633 ]
1634 : []),
1635 );
1636 }
1637 for (const membership of user.workspaces ?? []) {
1638 commands.push(
Workspace names and icons, and a component kit for every control1639 { 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 sidebar1640 { label: "All projects", hint: membership.slug, to: `/${membership.slug}/-/projects`, icon: <LayoutGrid size={15} /> },
1641 { label: "People", hint: membership.slug, to: `/${membership.slug}/-/people`, icon: <Users size={15} /> },
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.1642 { label: "Spend", hint: `${membership.slug} · Budgets and receipts`, to: `/${membership.slug}/-/spend`, icon: <Coins size={15} /> },
Sidebar: no settings flash on the way into a repository, and a better slide1643 { 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 tokens1644 { 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 page1645 { label: "Billing and plans", hint: `${membership.slug} · Settings`, to: `/${membership.slug}/-/billing`, icon: <CreditCard size={15} /> },
Sidebar: no settings flash on the way into a repository, and a better slide1646 { 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 look1647 { label: "Integrations", hint: membership.slug, to: `/${membership.slug}/-/integrations`, icon: <Plug size={15} /> },
Sidebar: no settings flash on the way into a repository, and a better slide1648 );
1649 }
1650 for (const listed of shell.repos) {
1651 commands.push({
Projects: what a workspace builds and runs, first on every page1652 label: listed.title ?? listed.name,
1653 hint: `${listed.namespace} · Project`,
Sidebar: no settings flash on the way into a repository, and a better slide1654 to: `/${listed.namespace}/${listed.name}`,
Projects: what a workspace builds and runs, first on every page1655 icon: <Box size={15} />,
Sidebar: no settings flash on the way into a repository, and a better slide1656 });
1657 }
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step1658 // "Put an agent on …": one per project, after the projects themselves.
1659 for (const listed of shell.repos) {
1660 if (repo && listed.namespace === repo.namespace && listed.name === repo.name) continue;
1661 commands.push({
1662 label: `Put an agent on ${listed.title ?? listed.name}`,
1663 hint: `${listed.namespace}/${listed.name}`,
1664 to: `/${listed.namespace}/${listed.name}/issues/new?agent=1`,
1665 icon: <Sparkles size={15} />,
1666 });
1667 }
Sidebar: no settings flash on the way into a repository, and a better slide1668 return commands;
1669}
1670
1671/**
Merge branch 'worktree-agent-aca4790ea223aa235'1672 * The page while the next one loads: after a moment it dims, under the
1673 * bar below, so it is plainly on its way out rather than frozen, and the
1674 * next page fades up from there. Sending a form does not dim it: the
1675 * form's button says it is working. Spread on the element holding the page.
1676 */
1677export function useLeaving() {
1678 const navigation = useNavigation();
1679 const method = navigation.formMethod?.toUpperCase();
1680 const leaving = navigation.state === "loading" && (method == null || method === "GET");
1681 return {
1682 "aria-busy": leaving || undefined,
1683 className: `transition-opacity motion-reduce:transition-none ${leaving ? "opacity-60 delay-200 duration-300" : "duration-150"}`,
1684 };
1685}
1686
1687/**
Sidebar: no settings flash on the way into a repository, and a better slide1688 * A bar across the top of the page while the next one loads, as GitHub
1689 * has: it appears at once, creeps towards the end while waiting, then fills
1690 * and fades when the page arrives.
1691 */
1692export function Progress() {
1693 const navigation = useNavigation();
1694 const busy = navigation.state !== "idle";
1695 const [width, setWidth] = useState(0);
1696 const [visible, setVisible] = useState(false);
1697 useEffect(() => {
1698 if (busy) {
1699 setVisible(true);
1700 setWidth(12);
1701 // Slows as it goes, never quite arriving until the page does.
1702 const timer = setInterval(() => setWidth((now) => now + (90 - now) * 0.12), 200);
1703 return () => clearInterval(timer);
1704 }
1705 setWidth((now) => (now > 0 ? 100 : 0));
1706 const fade = setTimeout(() => setVisible(false), 250);
1707 const reset = setTimeout(() => setWidth(0), 550);
1708 return () => {
1709 clearTimeout(fade);
1710 clearTimeout(reset);
1711 };
1712 }, [busy]);
1713 return (
1714 <div
1715 aria-hidden="true"
1716 className={`pointer-events-none fixed inset-x-0 top-0 z-[60] h-[3px] transition-opacity duration-300 ${
1717 visible ? "opacity-100" : "opacity-0"
1718 }`}
1719 >
1720 <div
1721 className="h-full bg-accent shadow-[0_0_10px_var(--color-accent)] transition-[width] duration-200 ease-out"
1722 style={{ width: `${width}%` }}
1723 />
1724 </div>
1725 );
1726}
1727
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)1728/** The top bar's way to g1t: the direct message with the workspace's orchestrator, opened or made. */
1729function AskG1tButton({ slug }: { slug: string }) {
1730 return (
1731 <Hint label="Ask g1t">
1732 <Link
1733 to={`/${slug}/-/chat?agent=g1t`}
1734 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.1735 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)1736 >
1737 <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.1738 <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)1739 </Link>
1740 </Hint>
1741 );
1742}
1743
Sidebar: no settings flash on the way into a repository, and a better slide1744/**
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.1745 * Which sidebar sits beside the page: each mode's own, or none. Today and
1746 * Apps are pages at full width, and so are g1t's public pages, such as a
1747 * profile, which are no workspace's. Without a workspace, only your own
1748 * settings and Notifications have one.
Chat and workspace agents: channels, DMs and named agents you talk to1749 */
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.1750function sidebarFor(mode: ModeKey, workspace: boolean): Panel | null {
1751 if (!workspace) return mode === "account" || mode === "notifications" ? mode : null;
1752 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)1753 return mode;
Chat and workspace agents: channels, DMs and named agents you talk to1754}
1755
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.1756/** The sidebars that sit beside the page, one per mode that has one. */
1757type 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)1758
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.1759/** 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 bar1760const MODE_MENU: Record<Panel, string> = {
1761 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.1762 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 bar1763 agents: "Agents",
1764 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.1765 notifications: "Notifications",
1766 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 bar1767 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.1768 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 bar1769};
1770
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.1771/** Whether a key press happened in something you type into, where Ctrl B is the editor's. */
1772function typing(target: EventTarget | null): boolean {
1773 if (!(target instanceof HTMLElement)) return false;
1774 return target.isContentEditable || target.closest("input, textarea, select, [contenteditable=''], [contenteditable='true'], [role='textbox']") != null;
1775}
1776
1777/** Ctrl B (⌘B on a Mac) shows or hides the sidebar, except while typing. */
1778function useSidebarShortcut(toggle: () => void) {
1779 useEffect(() => {
1780 const onKey = (event: KeyboardEvent) => {
1781 if (event.key.toLowerCase() !== "b" || event.altKey || event.shiftKey || !(event.ctrlKey || event.metaKey)) return;
1782 if (event.defaultPrevented || typing(event.target)) return;
1783 event.preventDefault();
1784 toggle();
1785 };
1786 window.addEventListener("keydown", onKey);
1787 return () => window.removeEventListener("keydown", onKey);
1788 }, [toggle]);
1789}
1790
1791/** The button that shows or hides the sidebar. */
1792function SidebarToggle({ onClick, open, className = "" }: { onClick: () => void; open: boolean; className?: string }) {
1793 const key = sidebarKeyLabel(typeof navigator === "undefined" ? null : navigator.platform);
1794 return (
1795 <Hint label={`Toggle sidebar (${key})`}>
1796 <button
1797 type="button"
1798 aria-label={open ? "Hide the sidebar" : "Show the sidebar"}
1799 aria-expanded={open}
1800 onClick={onClick}
1801 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}`}
1802 >
1803 <PanelLeft size={17} />
1804 </button>
1805 </Hint>
1806 );
1807}
1808
Chat and workspace agents: channels, DMs and named agents you talk to1809/**
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.1810 * 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.1811 * together. The dock, a floating bar of apps down the left; the mode's
1812 * sidebar, flat on the background beside it, which folds away with Ctrl B
1813 * and is a drawer below 1024px; and the page, a rounded panel inset from
1814 * the window, with its header across the top: the sidebar's toggle, where
1815 * you are, search, Ask g1t and Create new. On a phone the dock is a bar
1816 * along the bottom. Only for someone signed in; without a workspace yet,
1817 * there is no dock.
Sidebar: no settings flash on the way into a repository, and a better slide1818 */
1819export function AppShell({
1820 user,
1821 shell,
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1822 missing = false,
Sidebar: no settings flash on the way into a repository, and a better slide1823 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.1824 sidebarClosed = false,
Sidebar: no settings flash on the way into a repository, and a better slide1825 children,
1826}: {
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.1827 user: User;
Sidebar: no settings flash on the way into a repository, and a better slide1828 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.1829 /** 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 quotas1830 missing?: boolean;
Sidebar: no settings flash on the way into a repository, and a better slide1831 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.1832 /** Whether the person folded the sidebar away, as their cookie says. */
1833 sidebarClosed?: boolean;
Sidebar: no settings flash on the way into a repository, and a better slide1834 children: ReactNode;
1835}) {
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 const { pathname } = useLocation();
Sidebar: no settings flash on the way into a repository, and a better slide1837 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.1838 const [closed, setClosed] = useState(sidebarClosed);
Sidebar: no settings flash on the way into a repository, and a better slide1839 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.1840 const commands = useMemo(() => commandsFor(user, shell), [user, shell]);
Sidebar: no settings flash on the way into a repository, and a better slide1841
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.1842 // A new page closes the drawer.
Sidebar: no settings flash on the way into a repository, and a better slide1843 useEffect(() => setDrawer(false), [pathname]);
Search across all of g1t, Explore, and a command palette1844 usePaletteShortcut(() => setPalette((open) => !open));
Merge branch 'worktree-agent-aca4790ea223aa235'1845 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)1846 useVisualViewport();
Sidebar: no settings flash on the way into a repository, and a better slide1847
Chat and workspace agents: channels, DMs and named agents you talk to1848 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.1849 const ws = shell.workspace;
1850 const mode = modeOf(going ?? pathname, ws?.slug ?? null);
1851 const panel = sidebarFor(mode, ws != null);
1852 const code = ws ? hasCodeAccess(ws) : false;
Chat and workspace agents: channels, DMs and named agents you talk to1853 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)1854 // Notify: the feed socket's live counts (lib/notify-client.ts) once it has them; the page's until then.
1855 const live = useLiveBadges(ws?.slug);
1856 const chatUnread = chatSidebar
1857 ? unreadTotals(chatSidebar.entries)
1858 : live?.chat != null
1859 ? { unread: live.chat, mentions: live.mentions ?? 0 }
1860 : (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.1861 const notificationsUnread = live?.inbox ?? shell.inbox?.unread ?? 0;
1862 const unread = { notifications: notificationsUnread, chat: chatUnread.unread, mentions: chatUnread.mentions };
1863
1864 // Folding the sidebar away on a computer is remembered, so the next page is drawn the same from the server.
1865 const toggleSidebar = useCallback(() => {
1866 if (!window.matchMedia("(min-width: 1024px)").matches) {
1867 setDrawer((open) => !open);
1868 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)1869 }
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.1870 setClosed((was) => {
1871 document.cookie = sidebarCookie(!was, window.location.protocol === "https:");
1872 return !was;
1873 });
1874 }, []);
1875 useSidebarShortcut(useCallback(() => {
1876 if (panel) toggleSidebar();
1877 }, [panel, toggleSidebar]));
1878
1879 const inline = panel != null && !closed;
1880 const sidebarNode = () => {
1881 if (!panel) return null;
1882 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)1883 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.1884 case "code":
1885 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)1886 case "chat":
1887 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.1888 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.1889 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)1890 case "agents":
1891 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.1892 case "notifications":
1893 return <NotificationsSidebar counts={shell.inbox ?? null} />;
1894 case "people":
1895 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)1896 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.1897 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)1898 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.1899 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)1900 }
1901 };
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.1902 // The sidebar's top row: the workspace and its switcher, and the way to fold the sidebar or close the drawer.
1903 const sidebarTop = (inDrawer: boolean) => (
1904 <div className="flex h-14 shrink-0 items-center gap-1 pr-1 pl-1">
1905 {ws ? (
1906 <WorkspaceSwitcher user={user} workspace={ws} />
1907 ) : (
1908 <Link to="/" aria-label="g1t" className="mr-auto flex h-9 items-center rounded-md px-2">
1909 <Logo className="text-[1.125rem]" />
1910 </Link>
1911 )}
1912 {inDrawer ? (
1913 <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">
1914 <X size={16} />
1915 </button>
1916 ) : (
1917 <SidebarToggle open onClick={toggleSidebar} />
1918 )}
1919 </div>
1920 );
1921
1922 // 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)1923 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.1924 // Where the page panel starts: 8px past the dock (88px), or right after the sidebar (260px) when it is open.
1925 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";
1926 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 to1927
Sidebar: no settings flash on the way into a repository, and a better slide1928 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.1929 // The drawer is a sheet: a dialog that holds focus, closes on Escape or
1930 // a tap outside, and gives focus back to the button that opened it.
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1931 <Sheet open={drawer} onOpenChange={setDrawer}>
Sidebar: no settings flash on the way into a repository, and a better slide1932 <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.1933 {ws && (
1934 <div className="fixed top-2 bottom-2 left-2 z-40 hidden w-20 md:block">
1935 <Dock
1936 workspace={ws}
1937 pins={shell.pins ?? []}
1938 unread={unread}
1939 account={<AccountMenu user={user} />}
1940 />
1941 </div>
1942 )}
1943 {panel && (
1944 <aside
1945 aria-label={`${MODE_MENU[panel]} sidebar`}
1946 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" : ""}`}
1947 >
1948 {sidebarTop(false)}
1949 <div className="min-h-0 grow">{sidebarNode()}</div>
1950 </aside>
1951 )}
Chat and workspace agents: channels, DMs and named agents you talk to1952 <SheetContent
1953 side="left"
1954 showClose={false}
1955 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.1956 // 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)1957 onOpenAutoFocus={(event) => {
1958 event.preventDefault();
1959 (event.currentTarget as HTMLElement | null)?.focus();
1960 }}
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.1961 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 to1962 >
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.1963 <SheetTitle className="sr-only">{panel ? `${MODE_MENU[panel]} menu` : "Menu"}</SheetTitle>
1964 {sidebarTop(true)}
1965 <div className="min-h-0 grow">{sidebarNode()}</div>
Usage, Billing settings and prepaid AI credit; fixes from the UX audit1966 </SheetContent>
Sidebar: no settings flash on the way into a repository, and a better slide1967
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.1968 <div className={`min-h-dvh px-1.5 pt-(--frame-top) pb-(--tabbar-h) md:pr-2 ${pad}`}>
1969 <div className="flex min-h-[calc(100dvh-var(--frame-top)-var(--tabbar-h))] min-w-0 flex-col rounded-[14px] bg-bg">
1970 <header
1971 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" : ""}`}
Sidebar: no settings flash on the way into a repository, and a better slide1972 >
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.1973 {panel && (
1974 <SidebarToggle open={drawer} onClick={toggleSidebar} className={inline ? "lg:hidden" : ""} />
1975 )}
1976 {ws && (
1977 <span className={`flex min-w-0 shrink items-center gap-1.5 ${inline ? "lg:hidden" : ""}`}>
1978 <WorkspaceSwitcher user={user} workspace={ws} compact />
1979 <span aria-hidden="true" className="text-line-strong">
1980 /
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)1981 </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.1982 </span>
Inbox: a bell in the top bar opens it beside the page, and /inbox holds it all1983 )}
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.1984 <Breadcrumbs pathname={pathname} missing={missing} repo={shell.repo} workspace={ws?.slug ?? null} />
1985 <div className="ml-auto flex shrink-0 items-center gap-1.5">
1986 <button
1987 type="button"
1988 aria-label="Search or jump to"
1989 onClick={() => setPalette(true)}
1990 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 put1991 >
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.1992 <Search size={15} className="shrink-0" />
1993 <span className="hidden grow truncate text-left text-[0.8125rem] md:inline">Search or jump to</span>
1994 <PaletteKey className="hidden rounded bg-raised px-1.5 font-mono text-[0.625rem] text-muted ring-1 ring-line md:inline" />
1995 </button>
The Spend page says what a workspace spent, where it went and the budgets that hold it, in Workspace under Money: spent at price, agents' spend and the spend limit; by day; by agent, person, channel, model, kind of work and product; budgets from the workspace down to each person, agent and task, with what happens at 100%; the costliest tasks, each with a receipt of every session at the provider's price and what was charged; and how it's priced. Everyone sees what agents spent for them, and owners and billing managers the whole workspace; each person can have a monthly budget agents keep to, and the spend pill in the top bar shows your month or the workspace's against its limit. The spend guide says how.1996 {/* Your spend this month, or the workspace's for owners and billing managers; on a phone it is on Spend. */}
1997 {ws && (
1998 <span className="max-md:hidden">
1999 <SpendPill slug={ws.slug} mayWorkspace={ws.role === "owner" || !!ws.org_roles?.includes("billing_manager")} />
2000 </span>
2001 )}
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.2002 {ws && <AskG1tButton slug={ws.slug} />}
2003 {/* On a phone, Notifications is in the bottom bar. */}
2004 <span className="max-md:hidden">
2005 <NotificationsBell counts={shell.inbox ? { ...shell.inbox, unread: notificationsUnread } : null} />
2006 </span>
2007 <CreateMenu shell={shell} />
2008 {/* Without a workspace there is no dock: the account is here. */}
2009 {!ws && <AccountMenu user={user} side="bottom" />}
2010 </div>
2011 </header>
2012 {banner}
2013 <main id="content" tabIndex={-1} {...leaving} className={`min-w-0 grow outline-none ${leaving.className}`}>
2014 <InMain.Provider value={true}>{children}</InMain.Provider>
2015 </main>
2016 </div>
Sidebar: no settings flash on the way into a repository, and a better slide2017 </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.2018 {/* The panel's edge: a rounded frame over the page, with the background beyond it, so what scrolls stays inside. */}
2019 {!conversation && (
2020 <div
2021 aria-hidden="true"
2022 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 bar2023 />
2024 )}
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.2025 {ws && <BottomBar user={user} workspace={ws} pins={shell.pins ?? []} unread={unread} onReselect={panel ? () => setDrawer(true) : undefined} />}
2026 <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 audit2027 </Sheet>
Sidebar: no settings flash on the way into a repository, and a better slide2028 );
2029}
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.2030
2031/** Create new: a project, an issue in the one you are in, a workspace or a team. */
2032function CreateMenu({ shell }: { shell: ShellData }) {
2033 return (
2034 <DropdownMenu>
2035 <Hint label="Create new">
2036 <DropdownMenuTrigger
2037 aria-label="Create new"
2038 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"
2039 >
2040 <Plus size={16} />
2041 <ChevronDown size={13} className="text-muted max-sm:hidden" />
2042 </DropdownMenuTrigger>
2043 </Hint>
2044 <DropdownMenuContent align="end" className="min-w-52">
2045 {shell.repo && (
2046 <>
2047 <DropdownMenuLabel className="truncate">In {shell.repo.name}</DropdownMenuLabel>
2048 <DropdownMenuItem asChild>
2049 <Link to={`/${shell.repo.namespace}/${shell.repo.name}/issues/new`}>
2050 <CircleDot />
2051 New issue
2052 </Link>
2053 </DropdownMenuItem>
2054 {shell.repo.member && (
2055 <DropdownMenuItem asChild>
2056 <Link to={`/${shell.repo.namespace}/${shell.repo.name}/plans`}>
2057 <ListTree />
2058 Plan work
2059 </Link>
2060 </DropdownMenuItem>
2061 )}
2062 <DropdownMenuSeparator />
2063 </>
2064 )}
2065 <DropdownMenuItem asChild>
2066 <Link to="/?agent=new">
2067 <Sparkles />
2068 Put an agent on it
2069 </Link>
2070 </DropdownMenuItem>
2071 <DropdownMenuItem asChild>
2072 <Link to="/new">
2073 <Box />
2074 New project
2075 </Link>
2076 </DropdownMenuItem>
2077 <DropdownMenuItem asChild>
2078 <Link to="/new/github">
2079 <GitBranch />
2080 Import from GitHub
2081 </Link>
2082 </DropdownMenuItem>
2083 <DropdownMenuSeparator />
2084 <DropdownMenuItem asChild>
2085 <Link to="/workspaces/new">
2086 <Users />
2087 New workspace
2088 </Link>
2089 </DropdownMenuItem>
2090 {/* A team in the workspace you are in, for whoever it lets create one. */}
2091 {shell.workspace &&
2092 (mayCreateTeams(shell.workspace.team_creation, shell.workspace.role) ? (
2093 <DropdownMenuItem asChild>
2094 <Link to={`/${shell.workspace.slug}/-/teams/new`}>
2095 <UsersRound />
2096 New team
2097 </Link>
2098 </DropdownMenuItem>
2099 ) : (
2100 <DropdownMenuItem disabled>
2101 <UsersRound />
2102 New team
2103 <span className="ml-auto pl-3 text-xs text-faint">Owners only</span>
2104 </DropdownMenuItem>
2105 ))}
2106 </DropdownMenuContent>
2107 </DropdownMenu>
2108 );
2109}

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