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.
| Branches and Tags pages, each file's last commit, and the branch menu on files | 1 | import { BookOpen, Check, ChevronDown, Code2, File, FileArchive, Folder, FolderGit2, GitBranch, History, Search, SquareTerminal, Tag as TagIcon } from "lucide-react"; |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 2 | import { type ReactNode, Suspense } from "react"; |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 3 | import { Await, Form, Link } from "react-router"; |
| Initial g1t: services, event bus, intents and attempts | 4 | |
| Merge commit authors and hovercards: commits show their accounts, every name opens a card (repos 0016) | 5 | import type { BlobView as Blob, Branch, TreeView as RawTree } from "@g1t/contracts"; |
| 6 | ||
| 7 | import type { FileCommits, ShownBlame, ShownCommit } from "../lib/commit-people"; | |
| 8 | import { CommitAvatars, CommitNames } from "./commit-person"; | |
| API and MCP server, Rust identity service, registration, site redesign | 9 | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 10 | import type { DeploymentEnvironments } from "@g1t/contracts"; |
| 11 | ||
| Agents as a team: lifecycle, merge queue, billing and a new shell | 12 | import { BlameView } from "./blame-view"; |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 13 | import { DeploymentsPanel } from "./deployments-panel"; |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 14 | import { CodeLines } from "./code-lines"; |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 15 | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 16 | import { AgentSetup } from "./agent-setup"; |
| Merge branch 'worktree-agent-aaf03bdceac799c89' | 17 | import { useAddresses } from "../lib/addresses"; |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 18 | import { isImagePath } from "../lib/usercontent"; |
| Hosted agents: sandboxes on Cloudflare Containers started from an intent | 19 | import { CloneBox } from "./clone-box"; |
| Merge checks: statuses and check runs on every commit | 20 | import { type ChecksSource, CommitChecksBadge } from "./commit-checks"; |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 21 | import { type AboutData, RepoAboutPanel } from "./repo-about"; |
| API and MCP server, Rust identity service, registration, site redesign | 22 | import { Markdown } from "./markdown"; |
| Merge commit authors and hovercards: commits show their accounts, every name opens a card (repos 0016) | 23 | import { CopyLine, TimeAgo, notACredential } from "./ui"; |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 24 | import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger } from "./ui/dropdown-menu"; |
| 25 | import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"; | |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 26 | import { Hint } from "./ui/hint"; |
| Merge branch 'worktree-agent-aca4790ea223aa235' | 27 | import { SkeletonLine } from "./ui/skeleton"; |
| Initial g1t: services, event bus, intents and attempts | 28 | |
| 29 | function encodePath(path: string): string { | |
| 30 | return path.split("/").map(encodeURIComponent).join("/"); | |
| 31 | } | |
| 32 | ||
| 33 | function Breadcrumbs({ | |
| 34 | base, | |
| 35 | repo, | |
| 36 | gitRef, | |
| 37 | path, | |
| 38 | }: { | |
| 39 | base: string; | |
| 40 | repo: string; | |
| 41 | gitRef: string; | |
| 42 | path: string; | |
| 43 | }) { | |
| 44 | const segments = path.split("/").filter(Boolean); | |
| 45 | if (segments.length === 0) 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) | 46 | // On a phone, one line: the folders between the repository and the last |
| 47 | // two fold into an ellipsis that opens the deepest of them. | |
| 48 | const folded = segments.length - 2; | |
| 49 | const slash = <span className="mx-1.5 shrink-0 text-faint">/</span>; | |
| Initial g1t: services, event bus, intents and attempts | 50 | 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) | 51 | <nav aria-label="Path" className="flex min-w-0 basis-full items-center font-mono text-sm whitespace-nowrap text-muted sm:basis-auto sm:flex-wrap sm:whitespace-normal"> |
| 52 | <Link to={`${base}/tree/${gitRef}`} className="shrink-0 py-2 text-accent hover:underline sm:py-0"> | |
| Initial g1t: services, event bus, intents and attempts | 53 | {repo} |
| 54 | </Link> | |
| 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) | 55 | {folded > 0 && ( |
| 56 | <span className="flex shrink-0 items-center sm:hidden"> | |
| 57 | {slash} | |
| 58 | <Link | |
| 59 | to={`${base}/tree/${gitRef}/${encodePath(segments.slice(0, folded).join("/"))}`} | |
| 60 | aria-label={`Up to ${segments.slice(0, folded).join("/")}`} | |
| 61 | className="rounded px-1 py-2 text-accent hover:underline" | |
| 62 | > | |
| 63 | … | |
| 64 | </Link> | |
| 65 | </span> | |
| 66 | )} | |
| Initial g1t: services, event bus, intents and attempts | 67 | {segments.map((segment, i) => { |
| 68 | const to = encodePath(segments.slice(0, i + 1).join("/")); | |
| 69 | const last = i === segments.length - 1; | |
| 70 | 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) | 71 | <span |
| 72 | key={to} | |
| 73 | className={`${i < folded ? "hidden sm:flex" : "flex"} items-center ${last ? "min-w-0" : i === segments.length - 2 ? "min-w-0 shrink-[2]" : "shrink-0"}`} | |
| 74 | > | |
| 75 | {slash} | |
| Initial g1t: services, event bus, intents and attempts | 76 | {last ? ( |
| 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) | 77 | <span className="truncate font-medium text-fg">{segment}</span> |
| Initial g1t: services, event bus, intents and attempts | 78 | ) : ( |
| API and MCP server, Rust identity service, registration, site redesign | 79 | <Link |
| 80 | to={`${base}/tree/${gitRef}/${to}`} | |
| 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) | 81 | className="truncate py-2 text-accent hover:underline sm:py-0" |
| API and MCP server, Rust identity service, registration, site redesign | 82 | > |
| Initial g1t: services, event bus, intents and attempts | 83 | {segment} |
| 84 | </Link> | |
| 85 | )} | |
| 86 | </span> | |
| 87 | ); | |
| 88 | })} | |
| Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002) | 89 | </nav> |
| Initial g1t: services, event bus, intents and attempts | 90 | ); |
| 91 | } | |
| 92 | ||
| Merge checks: statuses and check runs on every commit | 93 | /** The bar above a file listing: the latest commit, its checks, and the way to the history. */ |
| Merge commit authors and hovercards: commits show their accounts, every name opens a card (repos 0016) | 94 | /** A tree as the page gets it: its latest commit with its people. */ |
| 95 | export type Tree = Omit<RawTree, "head"> & { head: ShownCommit | null }; | |
| 96 | ||
| 97 | function CommitBar({ commit, base, checks }: { commit: ShownCommit; base: string; checks?: ChecksSource }) { | |
| API and MCP server, Rust identity service, registration, site redesign | 98 | 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) | 99 | <div className="flex items-center gap-2.5 border-b border-line bg-surface px-3 py-2.5 text-sm sm:gap-3 sm:px-4"> |
| Merge commit authors and hovercards: commits show their accounts, every name opens a card (repos 0016) | 100 | <CommitAvatars commit={commit} /> |
| 101 | <span className="shrink-0 font-medium"> | |
| 102 | <CommitNames commit={commit} /> | |
| 103 | </span> | |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 104 | <Link to={`${base}/commit/${commit.hash}`} className="truncate text-muted hover:text-fg hover:underline"> |
| 105 | {commit.message.split("\n")[0]} | |
| 106 | </Link> | |
| Merge checks: statuses and check runs on every commit | 107 | <CommitChecksBadge checks={checks} sha={commit.hash} className="-ml-1.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) | 108 | <span className="ml-auto flex shrink-0 items-center gap-3 text-xs text-faint sm:gap-4"> |
| Merge checks: statuses and check runs on every commit | 109 | <Link to={`${base}/commit/${commit.hash}`} className="hidden font-mono hover:text-fg sm:inline"> |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 110 | {commit.hash.slice(0, 7)} |
| 111 | </Link> | |
| 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) | 112 | <span className="hidden sm:inline"> |
| 113 | <TimeAgo at={commit.authoredAt} /> | |
| 114 | </span> | |
| 115 | <Link to={`${base}/commits`} aria-label="History" className="-my-2 inline-flex items-center gap-1.5 py-2 font-medium text-muted hover:text-fg"> | |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 116 | <History size={14} /> |
| 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) | 117 | <span className="hidden sm:inline">History</span> |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 118 | </Link> |
| API and MCP server, Rust identity service, registration, site redesign | 119 | </span> |
| 120 | </div> | |
| 121 | ); | |
| 122 | } | |
| 123 | ||
| The code page reads like a forge: a branch menu, search and a Code button above the files | 124 | const BAR_BUTTON = |
| 125 | "inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md border border-line bg-surface px-3 text-sm transition-colors hover:border-line-strong hover:bg-raised data-[state=open]:border-line-strong"; | |
| 126 | ||
| 127 | /** Which branch is shown, and the others to switch to, at the same path. */ | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 128 | function BranchMenu({ |
| 129 | base, | |
| 130 | gitRef, | |
| 131 | path, | |
| 132 | branches, | |
| 133 | view = "tree", | |
| 134 | }: { | |
| 135 | base: string; | |
| 136 | gitRef: string; | |
| 137 | path: string; | |
| 138 | branches: Branch[]; | |
| 139 | /** Whether `path` is a folder or a file. */ | |
| 140 | view?: "tree" | "blob"; | |
| 141 | }) { | |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 142 | const rest = path ? `/${encodePath(path)}` : ""; |
| 143 | return ( | |
| 144 | <DropdownMenu> | |
| 145 | <DropdownMenuTrigger className={`${BAR_BUTTON} max-w-56 font-medium`}> | |
| 146 | <GitBranch size={14} className="text-faint" /> | |
| 147 | <span className="truncate font-mono text-[0.8125rem]">{gitRef}</span> | |
| 148 | <ChevronDown size={13} className="text-faint" /> | |
| 149 | </DropdownMenuTrigger> | |
| 150 | <DropdownMenuContent align="start" className="max-h-80 w-64 overflow-y-auto"> | |
| 151 | <DropdownMenuLabel>Switch branches</DropdownMenuLabel> | |
| 152 | {branches.map((branch) => ( | |
| 153 | <DropdownMenuItem key={branch.name} asChild> | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 154 | <Link to={`${base}/${view}/${encodePath(branch.name)}${rest}`}> |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 155 | <Check className={branch.name === gitRef ? "" : "invisible"} /> |
| 156 | <span className="truncate font-mono text-[0.8125rem]">{branch.name}</span> | |
| 157 | </Link> | |
| 158 | </DropdownMenuItem> | |
| 159 | ))} | |
| 160 | </DropdownMenuContent> | |
| 161 | </DropdownMenu> | |
| 162 | ); | |
| 163 | } | |
| 164 | ||
| 165 | /** Searches this repository's code on the search page, where it can be widened to all of g1t. */ | |
| 166 | function SearchCode({ repo }: { repo: string }) { | |
| 167 | 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) | 168 | <Form action="/search" role="search" className="relative ml-auto min-w-0 flex-1 basis-40 sm:w-64 sm:flex-none sm:basis-auto"> |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 169 | <Search size={14} className="pointer-events-none absolute top-1/2 left-2.5 -translate-y-1/2 text-faint" /> |
| 170 | <input | |
| 171 | name="q" | |
| 172 | {...notACredential()} | |
| 173 | placeholder="Search code" | |
| 174 | aria-label={`Search ${repo}`} | |
| 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) | 175 | className="h-9 w-full rounded-md border border-line bg-surface pr-3 pl-8 text-sm outline-none transition-colors placeholder:text-faint hover:border-line-strong focus:border-accent-dim sm:h-8" |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 176 | /> |
| 177 | <input type="hidden" name="repo" value={repo} /> | |
| 178 | <input type="hidden" name="type" value="code" /> | |
| 179 | </Form> | |
| 180 | ); | |
| 181 | } | |
| 182 | ||
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 183 | /** The one button for getting the code: clone over HTTPS or SSH, hand it to an agent, or download it. */ |
| 184 | function CodeButton({ path, gitRef }: { path: string; gitRef: string }) { | |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 185 | return ( |
| 186 | <Popover> | |
| 187 | <PopoverTrigger className="inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md bg-accent px-3 text-sm font-medium text-bg transition-colors hover:bg-accent/90"> | |
| 188 | <Code2 size={15} /> | |
| 189 | Code | |
| 190 | <ChevronDown size={13} /> | |
| 191 | </PopoverTrigger> | |
| 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) | 192 | <PopoverContent align="end" className="w-[min(24rem,calc(100vw-2rem))] p-0"> |
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 193 | <div className="p-4"> |
| 194 | <h2 className="mb-3 flex items-center gap-2 text-sm font-medium"> | |
| 195 | <SquareTerminal size={15} className="text-faint" /> | |
| 196 | Clone | |
| 197 | </h2> | |
| 198 | <CloneBox path={path} /> | |
| 199 | </div> | |
| 200 | <div className="border-t border-line p-1.5"> | |
| 201 | {/* A plain link: the browser downloads it, not the router. */} | |
| 202 | <a | |
| 203 | href={`/${path}/archive/${encodePath(gitRef)}.zip`} | |
| 204 | download | |
| 205 | className="flex items-center gap-2.5 rounded-md px-2.5 py-2 text-sm text-fg/90 transition-colors hover:bg-line hover:text-fg" | |
| 206 | > | |
| 207 | <FileArchive size={15} className="text-faint" /> | |
| 208 | Download ZIP | |
| 209 | </a> | |
| 210 | </div> | |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 211 | </PopoverContent> |
| 212 | </Popover> | |
| 213 | ); | |
| 214 | } | |
| 215 | ||
| 216 | /** Above the files: the branch and, at the root, how many there are, search and Code; below it, where you are. */ | |
| 217 | function CodeBar({ | |
| 218 | base, | |
| 219 | repo, | |
| 220 | gitRef, | |
| 221 | path, | |
| 222 | branches, | |
| 223 | }: { | |
| 224 | base: string; | |
| 225 | repo: { namespace: string; name: string }; | |
| 226 | gitRef: string; | |
| 227 | path: string; | |
| 228 | branches: Branch[] | null; | |
| 229 | }) { | |
| 230 | const full = `${repo.namespace}/${repo.name}`; | |
| 231 | const list = branches && branches.length > 0 ? branches : [{ name: gitRef, hash: "" }]; | |
| 232 | return ( | |
| 233 | <div className="mb-4 flex flex-wrap items-center gap-x-3 gap-y-2"> | |
| 234 | <BranchMenu base={base} gitRef={gitRef} path={path} branches={list} /> | |
| 235 | {path ? ( | |
| 236 | <Breadcrumbs base={base} repo={repo.name} gitRef={gitRef} path={path} /> | |
| 237 | ) : ( | |
| 238 | <> | |
| 239 | {branches && ( | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 240 | <Link to={`${base}/branches`} className="inline-flex items-center gap-1.5 text-sm text-muted hover:text-accent"> |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 241 | <GitBranch size={14} className="text-faint" /> |
| 242 | <span className="font-medium text-fg">{branches.length}</span> | |
| 243 | {branches.length === 1 ? "branch" : "branches"} | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 244 | </Link> |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 245 | )} |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 246 | <Link to={`${base}/tags`} className="inline-flex items-center gap-1.5 text-sm text-muted hover:text-accent"> |
| 247 | <TagIcon size={14} className="text-faint" /> | |
| 248 | Tags | |
| 249 | </Link> | |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 250 | <SearchCode repo={full} /> |
| Download ZIP from the Code button; a slimmer lifecycle panel; agent steps say what was done, not sandbox paths | 251 | <CodeButton path={full} gitRef={gitRef} /> |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 252 | </> |
| 253 | )} | |
| 254 | </div> | |
| 255 | ); | |
| 256 | } | |
| 257 | ||
| Branches and Tags pages, each file's last commit, and the branch menu on files | 258 | /** |
| 259 | * The files of a directory, each with the commit that last changed it. | |
| 260 | * `last` is undefined while those are still being read (the column holds | |
| 261 | * its place), and null when they could not be. | |
| 262 | */ | |
| 263 | function FileRows({ | |
| 264 | base, | |
| 265 | gitRef, | |
| 266 | prefix, | |
| 267 | entries, | |
| 268 | last, | |
| 269 | }: { | |
| 270 | base: string; | |
| 271 | gitRef: string; | |
| 272 | prefix: string; | |
| 273 | entries: Tree["entries"]; | |
| Merge commit authors and hovercards: commits show their accounts, every name opens a card (repos 0016) | 274 | last: FileCommits | null | undefined; |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 275 | }) { |
| 276 | const byName = new Map((last?.entries ?? []).map((entry) => [entry.name, entry.commit])); | |
| 277 | return ( | |
| Merge branch 'worktree-agent-aca4790ea223aa235' | 278 | // Busy while each entry's last commit is on its way; its cells keep their size. |
| 279 | <ul aria-busy={last === undefined || undefined} className="divide-y divide-line text-sm"> | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 280 | {entries.map((entry) => { |
| 281 | const isTree = entry.kind === "tree"; | |
| 282 | const Icon = isTree ? Folder : entry.kind === "gitlink" ? FolderGit2 : File; | |
| 283 | const commit = byName.get(entry.name); | |
| 284 | 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) | 285 | <li key={entry.name} className="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-4 px-4 transition-colors hover:bg-surface sm:grid-cols-[minmax(0,14rem)_minmax(0,1fr)_auto] lg:grid-cols-[minmax(0,18rem)_minmax(0,1fr)_auto]"> |
| 286 | {/* The whole row's height is the link's: a 44px target on a phone. */} | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 287 | <Link |
| 288 | to={`${base}/${isTree ? "tree" : "blob"}/${gitRef}/${prefix}${encodeURIComponent(entry.name)}`} | |
| 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) | 289 | className="flex min-h-11 min-w-0 items-center gap-3 py-2 hover:text-accent hover:underline sm:min-h-0" |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 290 | > |
| 291 | <Icon size={15} className={`shrink-0 ${isTree ? "text-accent-dim" : "text-faint"}`} /> | |
| 292 | <span className="truncate font-mono text-[0.8125rem]">{entry.name}</span> | |
| 293 | </Link> | |
| 294 | <span className="hidden min-w-0 sm:block"> | |
| 295 | {commit ? ( | |
| Merge branch 'worktree-agent-ae1299e92e4462012' | 296 | <Hint label={commit.message.split("\n")[0]}> |
| 297 | <Link to={`${base}/commit/${commit.hash}`} className="block animate-fade-in truncate text-muted hover:text-fg hover:underline"> | |
| 298 | {commit.message.split("\n")[0]} | |
| 299 | </Link> | |
| 300 | </Hint> | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 301 | ) : last === undefined ? ( |
| Merge branch 'worktree-agent-aca4790ea223aa235' | 302 | <SkeletonLine width="10rem" barClassName="max-w-full" /> |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 303 | ) : null} |
| 304 | </span> | |
| 305 | <span className="text-right text-xs whitespace-nowrap text-faint"> | |
| Merge branch 'worktree-agent-aca4790ea223aa235' | 306 | {commit ? <span className="animate-fade-in"><TimeAgo at={commit.authoredAt} /></span> : last === undefined ? <SkeletonLine className="justify-end" barClassName="w-12" /> : null} |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 307 | </span> |
| 308 | </li> | |
| 309 | ); | |
| 310 | })} | |
| 311 | </ul> | |
| 312 | ); | |
| 313 | } | |
| 314 | ||
| 315 | export function TreeView({ | |
| 316 | tree, | |
| 317 | branches = null, | |
| 318 | lastCommits = null, | |
| Merge checks: statuses and check runs on every commit | 319 | checks = null, |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 320 | about = null, |
| 321 | canPush = false, | |
| 322 | homepage = null, | |
| 323 | deployments = null, | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 324 | }: { |
| 325 | tree: Tree; | |
| 326 | branches?: Branch[] | null; | |
| 327 | /** Each entry's last commit, streamed in after the list. */ | |
| Merge commit authors and hovercards: commits show their accounts, every name opens a card (repos 0016) | 328 | lastCommits?: Promise<FileCommits | null> | null; |
| Merge checks: statuses and check runs on every commit | 329 | /** The latest commit's checks, streamed in. */ |
| 330 | checks?: ChecksSource; | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 331 | /** The About beside the files, at the root: streamed in after them. */ |
| 332 | about?: AboutData | null; | |
| 333 | /** Whether the viewer may push, for the About's "Create a new release". */ | |
| 334 | canPush?: boolean; | |
| 335 | /** The project's homepage; the repository's website when null. */ | |
| 336 | homepage?: string | null; | |
| 337 | /** The repository's environments, for the About's Deployments section. */ | |
| 338 | deployments?: DeploymentEnvironments | null; | |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 339 | }) { |
| Initial g1t: services, event bus, intents and attempts | 340 | const { repo, ref, path, head, entries, readme } = tree; |
| 341 | const base = `/${repo.namespace}/${repo.name}`; | |
| 342 | const prefix = path ? `${encodePath(path)}/` : ""; | |
| Merge branch 'worktree-agent-aaf03bdceac799c89' | 343 | const cloneUrl = `${useAddresses().site}${base}.git`; |
| Initial g1t: services, event bus, intents and attempts | 344 | |
| 345 | if (!head) { | |
| 346 | return ( | |
| API and MCP server, Rust identity service, registration, site redesign | 347 | <div className="mx-auto max-w-2xl rounded-xl border border-line bg-surface p-8"> |
| 348 | <h2 className="text-lg font-semibold tracking-tight"> | |
| 349 | This repository is empty | |
| 350 | </h2> | |
| 351 | <p className="mt-1 text-sm text-muted"> | |
| 352 | Push an existing project to it. Use an access token as the password. | |
| 353 | </p> | |
| 354 | <div className="mt-5 space-y-2"> | |
| 355 | <CopyLine prompt text={`git remote add g1t ${cloneUrl}`} /> | |
| 356 | <CopyLine prompt text={`git push -u g1t ${ref}`} /> | |
| 357 | </div> | |
| Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look | 358 | <h3 className="mt-7 text-sm font-medium">Or have your coding agent start it</h3> |
| 359 | <p className="mt-1 text-sm text-muted"> | |
| 360 | Connect it to g1t, then ask it to build the first version of{" "} | |
| 361 | <span className="font-mono text-fg">{repo.name}</span> and push it here. | |
| 362 | </p> | |
| 363 | <AgentSetup className="mt-3" /> | |
| Initial g1t: services, event bus, intents and attempts | 364 | </div> |
| 365 | ); | |
| 366 | } | |
| 367 | ||
| 368 | return ( | |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 369 | <div className={path ? "" : "grid gap-8 lg:grid-cols-[1fr_17rem]"}> |
| API and MCP server, Rust identity service, registration, site redesign | 370 | <div className="min-w-0"> |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 371 | <CodeBar base={base} repo={repo} gitRef={ref} path={path} branches={branches} /> |
| API and MCP server, Rust identity service, registration, site redesign | 372 | <div className="overflow-hidden rounded-xl border border-line"> |
| Merge checks: statuses and check runs on every commit | 373 | <CommitBar commit={head} base={base} checks={checks} /> |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 374 | {lastCommits ? ( |
| 375 | <Suspense fallback={<FileRows base={base} gitRef={ref} prefix={prefix} entries={entries} last={undefined} />}> | |
| 376 | <Await resolve={lastCommits} errorElement={<FileRows base={base} gitRef={ref} prefix={prefix} entries={entries} last={null} />}> | |
| 377 | {(last) => <FileRows base={base} gitRef={ref} prefix={prefix} entries={entries} last={last} />} | |
| 378 | </Await> | |
| 379 | </Suspense> | |
| 380 | ) : ( | |
| 381 | <FileRows base={base} gitRef={ref} prefix={prefix} entries={entries} last={null} /> | |
| 382 | )} | |
| Initial g1t: services, event bus, intents and attempts | 383 | </div> |
| API and MCP server, Rust identity service, registration, site redesign | 384 | |
| 385 | {readme?.text != null && ( | |
| The code page reads like a forge: a branch menu, search and a Code button above the files | 386 | <section id="readme" className="mt-6 scroll-mt-20 overflow-hidden rounded-xl border border-line"> |
| API and MCP server, Rust identity service, registration, site redesign | 387 | <h2 className="flex items-center gap-2 border-b border-line bg-surface px-4 py-2.5 text-sm font-medium"> |
| 388 | <BookOpen size={15} className="text-faint" /> | |
| 389 | {readme.name} | |
| 390 | </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) | 391 | <div className="p-4 sm:p-6"> |
| API and MCP server, Rust identity service, registration, site redesign | 392 | {/\.(md|markdown)$/i.test(readme.name) ? ( |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 393 | <Markdown |
| 394 | source={readme.text} | |
| 395 | repo={{ namespace: repo.namespace, name: repo.name }} | |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 396 | // Relative links in a README point into the repository, |
| 397 | // and its pictures at the files of the commit shown. | |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 398 | base={`/${repo.namespace}/${repo.name}/blob/${ref}${path ? `/${path}` : ""}`} |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 399 | rawBase={`/${repo.namespace}/${repo.name}/raw/${head.hash}${path ? `/${encodePath(path)}` : ""}`} |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 400 | /> |
| API and MCP server, Rust identity service, registration, site redesign | 401 | ) : ( |
| Fix a hydration mismatch in output that starts with a blank line | 402 | <pre className="whitespace-pre-wrap text-sm"><code>{readme.text}</code></pre> |
| API and MCP server, Rust identity service, registration, site redesign | 403 | )} |
| 404 | </div> | |
| 405 | </section> | |
| 406 | )} | |
| Initial g1t: services, event bus, intents and attempts | 407 | </div> |
| 408 | ||
| 409 | {!path && ( | |
| Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97 | 410 | <RepoAboutPanel |
| 411 | repo={repo} | |
| 412 | gitRef={ref} | |
| 413 | readme={Boolean(readme)} | |
| 414 | data={about ?? { about: null, watchers: null, packages: null }} | |
| 415 | canPush={canPush} | |
| 416 | homepage={homepage} | |
| 417 | deployments={<DeploymentsPanel base={base} summary={deployments} className="border-t border-line pt-4" />} | |
| 418 | /> | |
| Initial g1t: services, event bus, intents and attempts | 419 | )} |
| 420 | </div> | |
| 421 | ); | |
| 422 | } | |
| 423 | ||
| API and MCP server, Rust identity service, registration, site redesign | 424 | export function BlobView({ |
| 425 | blob, | |
| 426 | html, | |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 427 | blame, |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 428 | branches = null, |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 429 | notice, |
| 430 | marked, | |
| API and MCP server, Rust identity service, registration, site redesign | 431 | }: { |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 432 | /** For the branch menu; it shows the current branch alone without them. */ |
| 433 | branches?: Branch[] | null; | |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 434 | /** Said above the file, such as what is wrong with it. */ |
| 435 | notice?: ReactNode; | |
| 436 | /** Lines to mark as having a problem, 1-based. */ | |
| 437 | marked?: readonly number[]; | |
| API and MCP server, Rust identity service, registration, site redesign | 438 | blob: Blob; |
| Fast pages, required checks on the branch, self-hosted runners, honest incidents | 439 | /** Syntax-highlighted HTML per line, when the language is known. */ |
| 440 | html: string[] | null; | |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 441 | /** Shown instead of the plain file when asked for, with HTML per line. */ |
| Merge commit authors and hovercards: commits show their accounts, every name opens a card (repos 0016) | 442 | blame?: { blame: ShownBlame; lines: string[] | null } | null; |
| API and MCP server, Rust identity service, registration, site redesign | 443 | }) { |
| Initial g1t: services, event bus, intents and attempts | 444 | const { repo, ref, path, size, text } = blob; |
| 445 | const lines = text?.replace(/\n$/, "").split("\n"); | |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 446 | const base = `/${repo.namespace}/${repo.name}`; |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 447 | // The file as it is, on the usercontent origin (routes/repo/raw.ts). |
| 448 | const raw = `${base}/raw/${encodeURIComponent(ref)}/${encodePath(path)}`; | |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 449 | const toggle = (label: string, on: boolean, search: string) => ( |
| 450 | <Link | |
| 451 | to={{ search }} | |
| 452 | preventScrollReset | |
| 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) | 453 | className={`rounded px-2.5 py-1.5 transition-colors sm:px-2 sm:py-0.5 ${on ? "bg-raised text-fg" : "hover:text-fg"}`} |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 454 | > |
| 455 | {label} | |
| 456 | </Link> | |
| 457 | ); | |
| Initial g1t: services, event bus, intents and attempts | 458 | return ( |
| API and MCP server, Rust identity service, registration, site redesign | 459 | <div> |
| Branches and Tags pages, each file's last commit, and the branch menu on files | 460 | <div className="mb-4 flex flex-wrap items-center gap-x-3 gap-y-2"> |
| 461 | <BranchMenu | |
| 462 | base={base} | |
| 463 | gitRef={ref} | |
| 464 | path={path} | |
| 465 | branches={branches && branches.length > 0 ? branches : [{ name: ref, hash: "" }]} | |
| 466 | view="blob" | |
| 467 | /> | |
| 468 | <Breadcrumbs base={base} repo={repo.name} gitRef={ref} path={path} /> | |
| 469 | </div> | |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 470 | {notice} |
| API and MCP server, Rust identity service, registration, site redesign | 471 | <div className="overflow-hidden rounded-xl border border-line"> |
| 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) | 472 | <div className="flex items-center gap-3 border-b border-line bg-surface px-3 py-2 text-xs text-muted sm:px-4 sm:py-2.5"> |
| API and MCP server, Rust identity service, registration, site redesign | 473 | {lines && <span>{lines.length.toLocaleString("en-US")} lines</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) | 474 | <span className="hidden min-[400px]:inline">{size.toLocaleString("en-US")} bytes</span> |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 475 | <span className="ml-auto flex items-center gap-2"> |
| 476 | {lines && ( | |
| 477 | <span className="flex rounded-md border border-line p-0.5"> | |
| 478 | {toggle("Code", !blame, "")} | |
| 479 | {toggle("Blame", Boolean(blame), "?blame=1")} | |
| 480 | </span> | |
| 481 | )} | |
| 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) | 482 | <a href={raw} className="rounded-md border border-line px-2.5 py-2 transition-colors hover:text-fg sm:px-2 sm:py-1"> |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 483 | Raw |
| 484 | </a> | |
| 485 | </span> | |
| Initial g1t: services, event bus, intents and attempts | 486 | </div> |
| Agents as a team: lifecycle, merge queue, billing and a new shell | 487 | {blame && lines ? ( |
| 488 | <BlameView base={base} path={path} lines={lines} html={blame.lines} blame={blame.blame} /> | |
| API and MCP server, Rust identity service, registration, site redesign | 489 | ) : lines ? ( |
| Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar | 490 | <CodeLines lines={lines} html={html} marked={marked} /> |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 491 | ) : isImagePath(path) ? ( |
| 492 | <div className="flex justify-center bg-[repeating-conic-gradient(var(--color-raised)_0_25%,transparent_0_50%)] bg-[length:16px_16px] p-6"> | |
| 493 | <img src={raw} alt={path.split("/").pop() ?? path} className="max-h-[70vh] max-w-full" /> | |
| 494 | </div> | |
| Initial g1t: services, event bus, intents and attempts | 495 | ) : ( |
| API and MCP server, Rust identity service, registration, site redesign | 496 | <p className="p-6 text-sm text-muted"> |
| Merge g1tusercontent.com: registry answers run nothing in a browser, the site's pages run only their own scripts, repository files and avatars on their own origin, raw files rate limited per address | 497 | This file is binary or too large to show.{" "} |
| 498 | <a href={raw} className="text-accent hover:underline"> | |
| 499 | View it raw | |
| 500 | </a> | |
| 501 | . | |
| Initial g1t: services, event bus, intents and attempts | 502 | </p> |
| 503 | )} | |
| 504 | </div> | |
| 505 | </div> | |
| 506 | ); | |
| 507 | } |
This file's history is long; its oldest lines are credited to the oldest commit read.