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

New workspaces are told to connect a model, before anything fails1import { env } from "cloudflare:workers";
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)2import { data, redirect } from "react-router";
Device sign-in replaces registering and minting tokens over the API3
4import type { Route } from "./+types/home";
Social cards for every page: og.g1t.sh5import { page } from "../lib/meta";
Merge site-audit: SEO routes, analytics with consent first in Europe, security page, founder and X account, docs header; the tour opens on the pull request and leads with Code, on the real shell, with Agents and Docs working today6import { application, organization } from "../lib/structured-data";
Team plan, an open-source pool, monthly trials and honest metering; the sidebar for everyone; a workspace that stays put7import { WORKSPACE_COOKIE, chosenWorkspace } from "../lib/workspace-choice";
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)8import { readCookie } from "../lib/mission";
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step9import { type NotStarted, chosenRepo, delegateForm, issuePath, notStarted } from "../lib/delegate";
Device sign-in replaces registering and minting tokens over the API10import { Landing } from "../components/landing";
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)11import { repos as reposApi } from "../lib/services.server";
12import { assertSameOrigin, getViewer, requireUser } from "../lib/session.server";
13import { homePath } from "../lib/workspace-nav";
A free allowance on g1t's models, so anyone can try its agents14
Social cards for every page: og.g1t.sh15export function meta(args: Route.MetaArgs) {
Merge site-audit: SEO routes, analytics with consent first in Europe, security page, founder and X account, docs header; the tour opens on the pull request and leads with Code, on the real shell, with Agents and Docs working today16 return [
17 ...page(args, {
18 title: "g1t · Your team and its agents, working in one place",
19 description:
20 "Chat with your team and your agents in channels and DMs. Agents are teammates with a role, a personality and a budget, and their code lands through pull requests, checks and a merge queue. Chat is free on every plan, never per seat.",
21 }),
22 organization(),
23 application(20),
24 ];
Device sign-in replaces registering and minting tokens over the API25}
26
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms27/**
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)28 * g1t.sh: the landing page for a visitor. Someone signed in has a Home in
29 * their workspace (routes/workspace/home.tsx); Mission control's code
30 * panels are Code's Overview. `/?agent=new` and the rest of the query go
31 * with them.
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms32 */
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)33export async function loader({ context, request }: Route.LoaderArgs) {
34 const viewer = getViewer(context);
35 if (!viewer) return data({ signedIn: false as const });
36 const url = new URL(request.url);
37 const slug = chosenWorkspace(viewer.workspaces ?? [], readCookie(request.headers.get("cookie"), WORKSPACE_COOKIE))?.slug ?? null;
38 // A workspace-less account is sent to make one by the session (lib/session.server.ts).
39 if (!slug) throw redirect("/workspaces/new");
40 throw redirect(homePath(slug, url.search));
Mission control shows where you are needed and what agents landed without you; git answers in about 200ms41}
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API42
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step43/** What the composer said back, when the issue opened but the agent did not start, or nothing opened. */
44export type DelegateResult = { error: string; notStarted: null } | { error: null; notStarted: NotStarted };
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API45
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step46/**
47 * "Put an agent on it": opens an issue in one of the viewer's projects and
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent48 * puts g1t on it, then lands on the issue. When the agent could not
Thirteen MCP tools and classic token scopes; agents rate their confidence and can be put on an issue in one step49 * start, the issue is still open, and the composer says why and where to
50 * fix it.
51 */
52export async function action({ request, context }: Route.ActionArgs) {
53 assertSameOrigin(request);
54 const user = requireUser(context, request);
55 const form = await request.formData();
56 if (form.get("intent") !== "delegate") return data<DelegateResult>({ error: "Nothing to do.", notStarted: null }, { status: 400 });
57 const projects = await reposApi.list(user, { memberOnly: true }).catch(() => []);
58 const repo = chosenRepo(form.get("repo"), projects.map((repo) => ({ namespace: repo.namespace, name: repo.name })));
59 if (!repo) return data<DelegateResult>({ error: "Choose one of your projects.", notStarted: null }, { status: 400 });
60 const result = await env.RUNNER.delegate(user, repo, delegateForm(form));
61 if (!result.ok) return data<DelegateResult>({ error: result.error.message, notStarted: null }, { status: 400 });
62 const { issue, agent } = result.value;
63 const refused = notStarted(agent, repo, issue.number);
64 if (!refused) throw redirect(issuePath(repo, issue.number));
65 return data<DelegateResult>({ error: null, notStarted: refused });
66}
67
Mission control counts people's direct pushes to the default branch68
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)69export default function Home() {
70 return <Landing />;
Device sign-in replaces registering and minting tokens over the API71}

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