Skip to content
247 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.

Merge branch 'worktree-agent-ad7c6d88d93adc817'1import { Package, Plus } from "lucide-react";
2import { Outlet, data, redirect, useLocation, useNavigation } from "react-router";
Share the editor settings and Claude Code deploy permissions3
4import type { Route } from "./+types/layout";
Social cards for every page: og.g1t.sh5import { page } from "../../lib/meta";
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.6import { ButtonLink } from "../../components/ui";
7import { Avatar } from "../../components/ui/avatar";
8import { Badge } from "../../components/ui/badge";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas9import { WelcomeBanner } from "../../components/welcome";
10import { clearWelcome, welcomes } from "../../lib/invites";
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put11import { notFound } from "../../lib/not-found.server";
Agents and memory, checks and conflicts, profiles, slug renames, custom domains12import { redirectIfRenamed } from "../../lib/renamed.server";
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put13import { rememberWorkspace } from "../../lib/workspace-choice";
Merge branch 'worktree-agent-ad7c6d88d93adc817'14import { workspacePage, workspaceRedirect } from "../../lib/workspace-nav";
15import { WorkspacePageSkeleton } from "../../components/workspace-skeletons";
Share the editor settings and Claude Code deploy permissions16import { identity } from "../../lib/services.server";
17import { getViewer, roleIn } from "../../lib/session.server";
18
Social cards for every page: og.g1t.sh19export function meta({ loaderData, params, ...args }: Route.MetaArgs) {
20 return page(args, { title: `${loaderData?.workspace.name ?? params.owner} · g1t` });
Share the editor settings and Claude Code deploy permissions21}
22
Agents and memory, checks and conflicts, profiles, slug renames, custom domains23export async function loader({ params, context, request }: Route.LoaderArgs) {
Navigation: the workspace's own page with tabs, pins and recent in the sidebar24 const url = new URL(request.url);
Merge branch 'worktree-agent-ad7c6d88d93adc817'25 // `?tab=projects` and the like, from the tabs this page once had: that
26 // page's own address.
Navigation: the workspace's own page with tabs, pins and recent in the sidebar27 const moved = url.search ? workspaceRedirect(url.pathname, url.search) : null;
28 if (moved) throw redirect(moved);
29 const viewer = getViewer(context);
Merge branch 'worktree-agent-ad7c6d88d93adc817'30 const workspace = await identity.getWorkspace(params.owner);
Agents and memory, checks and conflicts, profiles, slug renames, custom domains31 if (!workspace) {
32 // A workspace's old name, after a rename: its pages are at the new one.
33 await redirectIfRenamed(request, params.owner);
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put34 throw notFound("workspace");
Agents and memory, checks and conflicts, profiles, slug renames, custom domains35 }
Navigation: the workspace's own page with tabs, pins and recent in the sidebar36 const role = roleIn(viewer, workspace.slug);
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put37 // Opening one of your workspaces makes it the one you are in.
Merge branch 'worktree-agent-ad7c6d88d93adc817'38 if (!role) return { workspace, role, welcome: false };
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put39 const secure = new URL(request.url).protocol === "https:";
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas40 const headers = new Headers({ "Set-Cookie": rememberWorkspace(workspace.slug, secure) });
41 // Just joined with an invite: welcomed once (routes/invite.tsx).
42 const welcome = welcomes(request.headers.get("cookie"), workspace.slug);
43 if (welcome) headers.append("Set-Cookie", clearWelcome(secure));
Merge branch 'worktree-agent-ad7c6d88d93adc817'44 return data({ workspace, role, welcome }, { headers });
Share the editor settings and Claude Code deploy permissions45}
46
47/** A workspace's own pages, each with its title and what it is for. */
48const PAGES: Record<string, { title: string; about: string }> = {
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)49 workspace: {
50 title: "Workspace",
51 about: "Who is in it, what it is on, and what it has spent this month. Everything about the workspace itself is in this sidebar.",
52 },
Merge branch 'worktree-agent-ad7c6d88d93adc817'53 settings: { title: "General", about: "The workspace's name, icon, address and description, who can create teams, and deleting it." },
Share the editor settings and Claude Code deploy permissions54 people: {
Navigation: the workspace's own page with tabs, pins and recent in the sidebar55 title: "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.56 about: "Everyone in the workspace, people and agents, in one directory: who they are, what they own, the teams they're on and who's around.",
57 },
58 members: {
59 title: "Members and invites",
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look60 about: "Members create repositories and have the base permission on each one. Owners are Admins on every repository, and also manage members, tokens, billing and integrations.",
61 },
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.62 "org-chart": {
63 title: "Org chart",
64 about: "Who reports to whom, with each team's agents beside the person who leads it.",
65 },
Navigation: the workspace's own page with tabs, pins and recent in the sidebar66 projects: {
67 title: "Projects",
68 about: "Everything the workspace builds and runs. Search, filter and sort them, and pin the ones you use most to keep them in your sidebar.",
69 },
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar70 teams: {
71 title: "Teams",
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.72 about: "People, agents, or both, with a lead, a channel, roles on repositories and a budget for their agents. Everyone on a team, agents included, knows who their teammates are.",
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar73 },
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look74 repositories: {
75 title: "Repositories",
76 about: "Every repository in the workspace: who can see it, whether it is archived, and the ones deleted recently.",
Share the editor settings and Claude Code deploy permissions77 },
78 tokens: {
79 title: "Access tokens",
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers80 about: "Tokens that belong to the workspace, not a person: for CI, integrations and agents that work for the whole team. Each has the permissions an owner gives it, in all of the workspace's repositories or the ones chosen.",
Settings: fine-grained tokens, workspace token Admin, workspace personal access token rules81 },
82 "personal-access-tokens": {
83 title: "Personal access tokens",
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers84 about: "Which of your members' own tokens may reach the workspace and for how long, the tokens made for it that wait for an owner's approval, and every token that can reach it.",
Share the editor settings and Claude Code deploy permissions85 },
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member86 packages: {
87 title: "Packages",
The Packages page names every registry it has88 about: "What the workspace publishes and installs, beside its code: container images, npm, Composer, Go, Cargo, Maven, NuGet and RubyGems, with the same members, roles and tokens.",
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member89 },
Share the editor settings and Claude Code deploy permissions90 usage: { title: "Usage", about: "What the workspace's agents cost, run by run, by repository, pull request and model." },
Merge the AI Gateway: Anthropic's Messages API on a workspace's tokens91 gateway: {
92 title: "AI Gateway",
93 about: "Your own code's model requests, sent with the workspace's access tokens: each one's model, tokens, cost and status.",
94 },
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look95 billing: { title: "Billing and plans", about: "The g1t plan, the trial, your spend limit and caps, prepaying, and every charge." },
Agents and memory, checks and conflicts, profiles, slug renames, custom domains96 agents: {
Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions97 title: "Agents",
98 about: "The workspace's agents together: what they are working on now, what waits on you, and where this month's agent budget went.",
Agents and memory, checks and conflicts, profiles, slug renames, custom domains99 },
100 memory: {
101 title: "Workspace memory",
102 about: "What holds across all of the workspace's projects, given to every agent in every one of them, beside each project's own memory.",
103 },
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API104 context: {
105 title: "Context",
106 about: "Everything the workspace builds and runs, and what it knows: a catalog built from its projects, memory with a review queue, one search over all of it, and a scorecard for each project.",
107 },
108 audit: {
109 title: "Audit log",
110 about: "Every action agents took with their run credentials, and every change people and tokens made: by whom, on whose behalf, to what, and whether it was allowed.",
111 },
112 guardrails: {
113 title: "Guardrails",
114 about: "What agents may reach, run, spend and take in every project's sandboxes. Each project can override these under its settings.",
115 },
Share the editor settings and Claude Code deploy permissions116 webhooks: {
117 title: "Webhooks",
118 about: "Every repository's events, sent to your own addresses as they happen. A repository can also have its own, under its settings.",
119 },
120 secrets: {
121 title: "Secrets and variables",
Secrets and variables: one list, rows per environment, for workflows and deployments122 about: "Shared with every repository, or the ones you link: read by workflows, deployments, or both. A repository's own row of the same key wins.",
Share the editor settings and Claude Code deploy permissions123 },
Security matches the workspace's other pages and leaves out deleted repositories; every section has a name in the trail124 security: {
125 title: "Security",
126 about: "Open alerts in every project: secrets found in pushes and history, and vulnerable dependencies. Each project's Security page has the details and the security update g1t opened for each.",
127 },
Share the editor settings and Claude Code deploy permissions128 integrations: {
129 title: "Integrations",
Integrations are a directory of connectors, for a workspace and for each person130 about:
131 "The tools your team works with, connected once for everyone in the workspace and its agents. Secrets are sealed when saved, and agents never see them.",
Share the editor settings and Claude Code deploy permissions132 },
133};
134
Merge branch 'worktree-agent-ad7c6d88d93adc817'135/** A workspace page's heading: its title and what it is for. */
136function PageHeader({ title, about }: { title: string; about: string }) {
Navigation: the workspace's own page with tabs, pins and recent in the sidebar137 return (
Merge branch 'worktree-agent-ad7c6d88d93adc817'138 <header className="mb-8 border-b border-line pb-6">
139 <h1 className="text-2xl font-semibold tracking-tight">{title}</h1>
140 <p className="mt-1.5 text-sm text-muted">{about}</p>
141 </header>
Navigation: the workspace's own page with tabs, pins and recent in the sidebar142 );
143}
144
The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work.145/** Artifacts' pages that are lists, not one artifact. */
146const ARTIFACT_LISTS = new Set(["new", "templates", "trash", "stale", "spaces"]);
147
148/** Whether the page (its path after `/-/`, in parts) is one artifact or a project's doc file. */
149function isArtifactPage(parts: string[]): boolean {
150 if (parts[0] !== "artifacts" || parts.length < 2) return false;
151 if (parts[1] === "repo") return true;
152 return !ARTIFACT_LISTS.has(parts[1]!) && parts.length === 2;
153}
154
Share the editor settings and Claude Code deploy permissions155export default function WorkspaceLayout({ loaderData }: Route.ComponentProps) {
Merge branch 'worktree-agent-ad7c6d88d93adc817'156 const { workspace, role, welcome } = loaderData;
Navigation: the workspace's own page with tabs, pins and recent in the sidebar157 const { pathname } = useLocation();
158 const going = useNavigation().location;
Merge branch 'worktree-agent-ad7c6d88d93adc817'159 // The workspace's own page is its overview. Its other pages are found
160 // from the sidebar, which lights the one you are on, and the top bar's
161 // trail leads back here; each has a heading of its own.
162 const here = workspacePage(pathname, workspace.slug);
163 // On the way to another of its pages: that page's heading and shape
164 // until it arrives.
165 const next = going && going.pathname !== pathname ? workspacePage(going.pathname, workspace.slug) : null;
166 const shown = next ?? here;
Navigation: the workspace's own page with tabs, pins and recent in the sidebar167 const parts = (pathname.split("/-/")[1] ?? "").split("/").filter(Boolean);
Chat and workspace agents: channels, DMs and named agents you talk to168 // Chat fills the page edge to edge: its conversation, thread and details
169 // are columns of their own (components/chat/channel.tsx).
170 if (parts[0] === "chat" && !next) return <Outlet />;
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)171 // Code's Overview lays itself out, as Mission control did.
172 if (parts[0] === "overview" && parts.length === 1 && !next) return <Outlet />;
The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work.173 // An open artifact, or a project's doc, fills the panel: its header runs edge to edge right under
174 // the top bar (components/folios/shell.tsx), and its page sets its own width.
175 if (isArtifactPage(parts) && !next) {
176 return (
177 <div className="px-4 pb-10 sm:px-6 lg:px-8">
178 <Outlet />
179 </div>
180 );
181 }
Merge branch 'worktree-agent-ad7c6d88d93adc817'182 if (shown !== "overview") {
183 const key = shown ?? parts[0] ?? "";
184 const heading = PAGES[key];
185 // A page within one (a single package or team) and a page that is
186 // coming (Insights) have headings of their own.
187 const titled = heading && (shown != null || parts.length === 1);
Packages, with a container registry on g1t.sh; workspaces deleted whole and kept 30 days; Members for every member188 return (
189 <div className="mx-auto max-w-5xl px-4 py-10 sm:px-8">
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)190 {titled && (
191 // A phone's Agents tab opens on its list of agents (agents/layout.tsx); the fleet's heading would sit above it.
192 <div className={key === "agents" ? "max-md:hidden" : undefined}>
193 <PageHeader title={heading.title} about={heading.about} />
194 </div>
195 )}
Merge branch 'worktree-agent-ad7c6d88d93adc817'196 {next ? <WorkspacePageSkeleton page={next} /> : <Outlet />}
Share the editor settings and Claude Code deploy permissions197 </div>
198 );
199 }
200 return (
201 <>
Merge branch 'worktree-agent-ad7c6d88d93adc817'202 {/* The workspace's own header band, above its overview. */}
Share the editor settings and Claude Code deploy permissions203 <div className="border-b border-line bg-surface/60">
Merge branch 'worktree-agent-ad7c6d88d93adc817'204 <div className="mx-auto max-w-6xl px-4 py-8">
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas205 {welcome && (
206 <div className="mb-6">
207 <WelcomeBanner title={`You're in ${workspace.name}`}>
208 You joined as a {role}. Its projects, issues and agents are all here.
209 </WelcomeBanner>
210 </div>
211 )}
Share the editor settings and Claude Code deploy permissions212 <div className="flex flex-wrap items-center gap-4">
Workspace names and icons, and a component kit for every control213 <Avatar name={workspace.slug} image={workspace.avatar} size={52} square />
Share the editor settings and Claude Code deploy permissions214 <div className="min-w-0 grow">
215 <div className="flex flex-wrap items-center gap-2.5">
216 <h1 className="truncate text-2xl font-semibold tracking-tight">
217 {workspace.name}
218 </h1>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.219 {role && <Badge size="md">{role}</Badge>}
Share the editor settings and Claude Code deploy permissions220 </div>
221 <p className="font-mono text-sm text-muted">g1t.sh/{workspace.slug}</p>
222 </div>
Merge branch 'worktree-agent-ad7c6d88d93adc817'223 {role ? (
Share the editor settings and Claude Code deploy permissions224 <ButtonLink to={`/new?workspace=${workspace.slug}`}>
225 <Plus size={15} />
Projects live: fixes from walking them end to end226 New project
Share the editor settings and Claude Code deploy permissions227 </ButtonLink>
Merge branch 'worktree-agent-ad7c6d88d93adc817'228 ) : (
229 // A visitor's sidebar is not this workspace's: its packages
230 // are a link here, as its projects are below.
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.231 <ButtonLink to={`/${workspace.slug}/-/packages`} variant="outline" prefetch="intent">
Merge branch 'worktree-agent-ad7c6d88d93adc817'232 <Package size={15} />
233 Packages
234 </ButtonLink>
Share the editor settings and Claude Code deploy permissions235 )}
236 </div>
237 {workspace.description && (
238 <p className="mt-4 max-w-2xl text-sm text-muted">{workspace.description}</p>
239 )}
240 </div>
241 </div>
242 <div className="mx-auto max-w-6xl px-4 py-8">
Merge branch 'worktree-agent-ad7c6d88d93adc817'243 {next ? <WorkspacePageSkeleton page="overview" /> : <Outlet />}
Share the editor settings and Claude Code deploy permissions244 </div>
245 </>
246 );
247}

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