Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
62 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.

Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running1/**
Anyone on g1t can invite a friend again: Invite a friend, in the account menu with how many are left beside it, opens Settings → Invites to g1t with a dialog for their email address and a note. The friend gets an email from them whose link opens sign-up with the address filled in and, because it came from that email, confirmed; their account starts with a workspace of its own, and the page lists every invite sent with where it stands (Pending, confirming their email, Joined as @them), with Copy link, Send again and Revoke on each. It is word of mouth, never a gate: sign-ups stay open to everyone, nothing asks for an invite, and running out says friends can still sign up without one.2 * The Invites page: every invite, to find and revoke one, with invites to
3 * g1t from Invite a friend on their own tab, and more of those for a
4 * person. Anyone may register, so there is no waitlist and no shared link
5 * to manage; an invite is never needed to sign up. No Workers imports, so
6 * it can be tested under Node. Identity checks everything again.
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running7 */
8
Anyone on g1t can invite a friend again: Invite a friend, in the account menu with how many are left beside it, opens Settings → Invites to g1t with a dialog for their email address and a note. The friend gets an email from them whose link opens sign-up with the address filled in and, because it came from that email, confirmed; their account starts with a workspace of its own, and the page lists every invite sent with where it stands (Pending, confirming their email, Joined as @them), with Copy link, Send again and Revoke on each. It is word of mouth, never a gate: sign-ups stay open to everyone, nothing asks for an invite, and running out says friends can still sign up without one.9/** The page's tabs: every invite, or only invites to g1t (Invite a friend). */
10export type InvitesTab = "all" | "g1t";
11
12export function invitesTab(raw: string | null | undefined): InvitesTab {
13 return raw === "g1t" ? "g1t" : "all";
14}
15
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.16/** The page's address, with its search. */
17export function invitesHref(params: Record<string, string | null | undefined> = {}): string {
18 const search = new URLSearchParams();
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running19 for (const [key, value] of Object.entries(params)) if (value) search.set(key, value);
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.20 const query = search.toString();
21 return query ? `/invites?${query}` : "/invites";
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running22}
23
24/** The flash messages the page redirects back with (`?done=`). */
25export const INVITES_DONE: Record<string, string> = {
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.26 revoked: "Invite revoked. It stops working at once.",
Anyone on g1t can invite a friend again: Invite a friend, in the account menu with how many are left beside it, opens Settings → Invites to g1t with a dialog for their email address and a note. The friend gets an email from them whose link opens sign-up with the address filled in and, because it came from that email, confirmed; their account starts with a workspace of its own, and the page lists every invite sent with where it stands (Pending, confirming their email, Joined as @them), with Copy link, Send again and Revoke on each. It is word of mouth, never a gate: sign-ups stay open to everyone, nothing asks for an invite, and running out says friends can still sign up without one.27 granted: "Granted. It applies at once.",
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running28};
29
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.30/** The flash for `?done=`. */
31export function doneMessage(done: string | null): string | null {
32 return done ? (INVITES_DONE[done] ?? null) : null;
Costs: a statement that keeps usage sold, running g1t, subscriptions and what was given away (comped, free use, trial, pool) apart, and says who was paid; free use carries its own cost; the run button says it is running33}
34
Merge main into rm-agents: mirroring removal, open signups, free-tier limits, the g1t CLI and runner fixes, with the agent removal kept. The CLI's table of operations is regenerated from the API without the agent, customize and AI credit operations; no CLI command used them.35/** What an account made with a shared link, before registration opened, says about where it came from. */
Merge shared invite links: label, uses, expiry, domains; joined through recorded (identity 0038)36export function joinedThrough(label: string): string {
37 return `Joined through ${label}`;
38}
Anyone on g1t can invite a friend again: Invite a friend, in the account menu with how many are left beside it, opens Settings → Invites to g1t with a dialog for their email address and a note. The friend gets an email from them whose link opens sign-up with the address filled in and, because it came from that email, confirmed; their account starts with a workspace of its own, and the page lists every invite sent with where it stands (Pending, confirming their email, Joined as @them), with Copy link, Send again and Revoke on each. It is word of mouth, never a gate: sign-ups stay open to everyone, nothing asks for an invite, and running out says friends can still sign up without one.39
40/** The most invites one grant gives or takes back (`MAX_INVITE_GRANT` in the contracts). */
41export const MAX_GRANT = 1000;
42
43const USERNAME = /^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){0,38}$/;
44
45export type Grant = { username: string; amount: number; note: string };
46
47/** A grant of invites to g1t, as typed: who, how many (negative takes back), and why. */
48export function parseGrant(form: { get(name: string): unknown }): { ok: true; value: Grant } | { ok: false; error: string } {
49 const read = (name: string) => {
50 const value = form.get(name);
51 return typeof value === "string" ? value.trim() : "";
52 };
53 const username = read("username").replace(/^@/, "").toLowerCase();
54 if (!USERNAME.test(username)) return { ok: false, error: `“${read("username")}” is not a username.` };
55 const raw = read("amount");
56 if (!/^-?\d+$/.test(raw)) return { ok: false, error: "Give a whole number of invites, such as 10, or -5 to take some back." };
57 const amount = Number(raw);
58 if (amount === 0 || Math.abs(amount) > MAX_GRANT) return { ok: false, error: `Grant between 1 and ${MAX_GRANT} invites.` };
59 const note = read("note");
60 if (note.length < 3) return { ok: false, error: "Say why, for the record." };
61 return { ok: true, value: { username, amount, note: note.slice(0, 500) } };
62}

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