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
919 linesCodeBlameRaw
1import { ArrowUpRight } from "lucide-react";
2
3import { type FeaturePlan, type FreeTier, MICROS_PER_DOLLAR, type Price } from "@g1t/contracts";
4
5import type { Route } from "./+types/pricing";
6import { wholeDollars } from "../lib/billing";
7import { page } from "../lib/meta";
8import { application, faqPage } from "../lib/structured-data";
9import { TimeAgo } from "../components/ui";
10import { Card } from "../components/ui/card";
11import { billing } from "../lib/services.server";
12
13export function meta(args: Route.MetaArgs) {
14 const plan = args.loaderData?.book?.plans?.find((p) => p.feature === "plan") ?? DEFAULT_PLAN;
15 return [
16 ...page(args, {
17 title: `g1t pricing - $${plan.monthlyCents / 100} per workspace, never per seat, models at cost`,
18 description:
19 "People chat free on every plan, and the forge is free. One plan, $20 a month per workspace with $10 of usage included. Models at the provider's price, plus a flat agent rate for what g1t runs around every model call; everything else g1t runs at cost plus 20%. Your own runners are free. No seats, ever.",
20 }),
21 application(plan.monthlyCents / 100),
22 faqPage(FAQ),
23 ];
24}
25
26export async function loader() {
27 const [book, status] = await Promise.all([billing.prices().catch(() => null), billing.status().catch(() => null)]);
28 return { book, free: status?.free ?? false };
29}
30
31/** A price in dollars, with as many digits as it needs to say anything. */
32function money(micros: number): string {
33 const dollars = micros / MICROS_PER_DOLLAR;
34 if (dollars >= 1) return `$${dollars.toFixed(2)}`;
35 // Three places for a fraction of a cent ($0.024), two when the third is 0 ($0.25).
36 if (dollars >= 0.01) return `$${dollars.toFixed(3).replace(/(\.\d\d)0$/, "$1")}`;
37 return `$${dollars.toPrecision(2)}`;
38}
39
40/** Per second is easier to read per minute. */
41function perUnit(price: Price, micros: number): string {
42 return price.unit === "second" ? `${money(micros * 60)} a minute` : `${money(micros)} per ${price.unit}`;
43}
44
45function gigabytes(bytes: number): string {
46 return `${Math.round((bytes / 1e9) * 10) / 10} GB`;
47}
48
49function count(n: number): string {
50 return n.toLocaleString("en-US");
51}
52
53/** Price-book rows the table shows in rows of their own, or not at all. */
54const SHOWN_APART = new Set([
55 "app_month",
56 "agent_models",
57 "agent_tokens",
58 "agent_tokens_own",
59 "agent_token_weight_input",
60 "agent_token_weight_output",
61 "agent_token_weight_cache_read",
62 "agent_token_weight_cache_write",
63 "gateway_models",
64 "card_fee_percent",
65 "card_fee_fixed",
66 "security_activation",
67]);
68
69/** How each kind of token counts toward the agent rate, from the price book: `input ×1, …`. */
70function tokenWeights(prices: { meter: string; costMicros: number }[]): string {
71 const weight = (kind: string) => {
72 const row = prices.find((p) => p.meter === `agent_token_weight_${kind}`);
73 return row ? Number((row.costMicros / 1_000_000).toFixed(3)) : 1;
74 };
75 return `input ×${weight("input")}, output ×${weight("output")}, cache reads ×${weight("cache_read")}, cache writes ×${weight("cache_write")}`;
76}
77
78/** What the page says when billing cannot be reached: the published defaults. */
79const DEFAULT_FREE: Required<FreeTier> = {
80 trialWorkspaceMicros: 5_000_000,
81 trialMonthlyPoolMicros: 100_000_000,
82 ossPoolMicros: 25_000_000,
83 ossRepoMicros: 2_000_000,
84 freePrivateStorageBytes: 1_000_000_000,
85 auditRetentionDays: 7,
86 planAuditRetentionDays: 90,
87 minChargeMicros: 5_000_000,
88 gitOperationsIncluded: 50_000,
89 paidStartCeilingMicros: 100_000_000,
90 overageForgiveCostMicros: 50_000_000,
91};
92
93const DEFAULT_PLAN: FeaturePlan = {
94 feature: "plan",
95 title: "g1t",
96 monthlyCents: 2000,
97 includes: [
98 "$10 of usage each month, used first: models at the provider's price with the g1t agent rate, everything else g1t runs at cost plus 20%",
99 "Everyone in the workspace at one price, never per person",
100 "Unlimited projects, previews and repositories",
101 "Agents, checks, workflows, the merge queue, deployments, semantic search, and Security and quality on private repositories",
102 "Usage past $10 is charged the same way, up to your spend limit",
103 ],
104 overage:
105 "Everything g1t runs is metered from the first unit at what it costs g1t plus 20%. Models are billed at the provider's price, with no markup, plus the g1t agent rate on their tokens, on your own model keys too. Your own runners cost nothing. Unused included usage does not roll over.",
106};
107
108/** How each part of a workspace is charged. */
109const WORKSPACE_CHARGES: { what: string; how: string; soon?: boolean }[] = [
110 {
111 what: "People chatting",
112 how: "Included on every plan, the free one too: channels, direct messages, threads, mentions and live delivery. No seats, and history is never cut off.",
113 },
114 { what: "Docs", how: "Included on every plan, like chat: pages, live editing and history.", soon: true },
115 {
116 what: "An agent replying in chat",
117 how: "The model provider's price, with no markup, plus the g1t agent rate on the tokens it used. Paid from the plan's included usage, then AI credit, and counted against that agent's budget.",
118 },
119 {
120 what: "An agent working on code",
121 how: "The same model price and agent rate, plus sandbox time at cost plus 20%. On your own runner, that time is free.",
122 },
123 {
124 what: "An agent on your own provider",
125 how: "Your provider bills you for the model directly. g1t charges the agent rate, for passing its calls through g1t's model gateway with your key kept secret.",
126 },
127 {
128 what: "How hard an agent works",
129 how: "Each agent has an effort setting, Auto, Low, Medium, High or Max, shown with what a typical task has cost at each level. Lower effort starts on a cheaper model, reasons less and takes fewer steps.",
130 },
131 {
132 what: "Files in chat and Docs",
133 how: "The storage meter, at cost plus 20%, past what is free.",
134 soon: true,
135 },
136 { what: "An idle agent", how: "Nothing. An agent costs money only while it is answering or working." },
137];
138
139const FAQ: { q: string; a: string }[] = [
140 {
141 q: "Do people pay to use Chat?",
142 a: "No. Messages, channels, threads and live delivery are included on every plan, with no per-person price and no limit on history. A workspace on the plan can add as many people as it likes at the same price.",
143 },
144 {
145 q: "Who pays for an agent's reply?",
146 a: "The workspace the agent belongs to. Each reply is charged as the model's price plus the agent rate, and counts against that agent's monthly budget, whoever asked it.",
147 },
148 {
149 q: "What does an agent cost when nobody talks to it?",
150 a: "Nothing. Agents have no monthly fee. They are charged only for replies and work, so an agent you made and forgot costs nothing.",
151 },
152 {
153 q: "How do I stop an agent from spending too much?",
154 a: "Give it a monthly budget and a cap per task. At its budget it stops taking new work and says so in the channel. The workspace's spend limit and the per-run caps still apply above it.",
155 },
156 {
157 q: "How do I spend less without worse work?",
158 a: "Lower an agent's effort, or let Spend suggest it. Every week g1t checks each agent's finished sessions: when a cheaper effort level was accepted as often on the same agent's work, Spend shows the suggestion with the numbers and an Apply button. With too little history, it says so instead.",
159 },
160 {
161 q: "Why is there an agent rate on my own model keys?",
162 a: "Your agents' calls still go through g1t: its model gateway keeps your key out of every sandbox, routes each call, adds the context and passes it to your provider. The agent rate pays for running that. Your provider bills the model itself.",
163 },
164 {
165 q: "Can agents use our own model provider?",
166 a: "Yes. Connect a provider in Integrations and limit an agent to it. The provider bills you for the model; g1t charges the agent rate for your own model key only.",
167 },
168 {
169 q: "Does adding the whole company cost more?",
170 a: "No. There are no seats. People who only chat, and ask agents questions, cost nothing until their questions use an agent; then the agent's reply is charged like any other.",
171 },
172 {
173 q: "What does moving from GitHub cost, and can we leave again?",
174 a: "Moving in is an import: bring repositories across from GitHub with every branch, tag and their issues, or keep a mirror that follows GitHub while you try g1t. Your code is plain git and g1t is MIT licensed, so leaving is a git clone, and the core forge runs on your own machine with Docker Compose.",
175 },
176 {
177 q: "Is Docs included?",
178 a: "Docs is coming soon. When it ships, pages, editing and history are included on every plan, like chat. Files are on the storage meter.",
179 },
180];
181
182/** The ways to reach g1t about an enterprise account. */
183const ENTERPRISE_MAIL = "mailto:hey@flagon.io?subject=Enterprise%20billing%20for%20g1t";
184
185const HOW = [
186 {
187 title: "Our cost, passed through",
188 body: "Every sandbox second, build and app request costs g1t money at Cloudflare. Each is metered and charged at that cost plus 20%, from the first second and the first request. Models are charged at the provider's price with no markup, plus a flat agent rate per million tokens for what g1t runs around every model call, from prepaid AI credit. Use a little, pay a little.",
189 },
190 {
191 title: "Prices follow costs, by themselves",
192 body: "Model runs are charged at what Cloudflare's AI Gateway priced each request at, so a provider's price change reaches you the same day. Every day, sandbox, build and app costs are checked against what Cloudflare billed g1t; when one moves, its price moves with it, and the change is listed below. The rest are Cloudflare's published prices, marked as such.",
193 },
194 {
195 title: "The 20% is the overhead",
196 body: "It pays for running g1t and for building and keeping up the features you use. The same 20% on everything but models, whose overhead is the agent rate, and nothing bundled in.",
197 },
198 {
199 title: "Your own runners are free",
200 body: "Agents, checks and workflows on your own hardware cost nothing here. On your own model keys, your provider bills the model and g1t charges only the agent rate.",
201 },
202 {
203 title: "No seats, ever",
204 body: "Once a workspace is on the plan, add as many people and agents as you like. It pays one flat price for the plan, and for what it uses past what the plan includes.",
205 },
206 {
207 title: "Prices exclude tax",
208 body: "Every price here is before tax. Stripe adds sales tax, VAT or GST where it applies, worked out from the billing address, and shows it as its own line before you pay and on every receipt and invoice. A valid business tax ID is applied where the law says so.",
209 },
210 {
211 title: "Card fees are passed on, nothing more",
212 body: "Paying by card adds Stripe's card processing fee as its own line, shown before you pay, so the 20% is never spent on fees. A bank transfer or invoiced billing has no card fee.",
213 },
214];
215
216/** One row of the free-and-plan table. */
217type Row = { what: string; free: string; plan: string; note?: string };
218
219function rows(tier: Required<FreeTier>): Row[] {
220 return [
221 {
222 what: "Chat",
223 free: "Included, for the people already in the workspace",
224 plan: "Included, for unlimited members",
225 note: "Channels, direct messages, threads, mentions and live delivery. History is never cut off.",
226 },
227 {
228 what: "Docs (coming soon)",
229 free: "Included",
230 plan: "Included",
231 note: "Pages, live editing and history, once Docs ships.",
232 },
233 {
234 what: "Workspace agents",
235 free: "After a card check, from the trial",
236 plan: "From the plan's included usage, then AI credit, under each agent's budget",
237 note: "Replies and work are charged as model price plus the g1t agent rate. An idle agent costs nothing.",
238 },
239 {
240 what: "The forge",
241 free: "Free",
242 plan: "Included",
243 note: "Public and private repositories, issues, pull requests, reviews, protected branches, code owners, search and Explore.",
244 },
245 {
246 what: "Agents, checks, workflows, merge queue",
247 free: "After a card check: the trial, and the open-source pool for checks, workflows and the merge queue on public repositories",
248 plan: "From the plan's included usage, then at cost plus 20%",
249 },
250 {
251 what: "Projects and previews",
252 free: "Not available: deployments run on g1t's machines",
253 plan: "Unlimited, and never charged for. An app no one visits costs nothing.",
254 },
255 {
256 what: "Deployments",
257 free: "Not available",
258 plan: "Builds by the second, app requests, CPU time and custom domains, each from the first at cost plus 20%",
259 },
260 {
261 what: "Semantic search",
262 free: "After a card check, from the trial",
263 plan: "From the plan's included usage, then at cost plus 20%",
264 },
265 {
266 what: "Private storage",
267 free: `${gigabytes(tier.freePrivateStorageBytes)}, never charged. Past it, pushes to private repositories stop until you make room or start the plan.`,
268 plan: `${gigabytes(tier.freePrivateStorageBytes)} free, then at cost plus 20%. Pushes never stop.`,
269 note: "Public repositories are never charged for storage.",
270 },
271 {
272 what: "Git operations",
273 free: `${count(tier.gitOperationsIncluded)} a month, never charged. Past it, slowed to 60 an hour until the month turns.`,
274 plan: `${count(tier.gitOperationsIncluded)} a month free, then at cost plus 20%. Never slowed.`,
275 note: "Clones, fetches and pushes through g1t.",
276 },
277 {
278 what: "Actions cache",
279 free: "2 GiB an entry and 10 GiB a repository, never charged",
280 plan: "The same limits, with what it stores at cost plus 20%",
281 },
282 {
283 what: "Audit log",
284 free: `${tier.auditRetentionDays} days, with export`,
285 plan: `${tier.planAuditRetentionDays} days, with export`,
286 note: "Longer by arrangement. Older entries are deleted each day.",
287 },
288 {
289 what: "Secret scanning, push protection, vulnerability alerts, security updates",
290 free: "Included",
291 plan: "Included",
292 note: "Custom patterns, validity checks, code scanning, dependency review and the security overview on private repositories come with the plan, with no price of their own: their scans are charged at cost plus 20%. On public repositories they are free.",
293 },
294 { what: "Single sign-on", free: "On every plan, once it is built", plan: "On every plan, once it is built" },
295 {
296 what: "Members",
297 free: "Only the people already in it: a free workspace cannot add members, invite people or invite outside collaborators",
298 plan: "Unlimited, never per seat",
299 note: "Each person can own one free workspace. More workspaces need the plan.",
300 },
301 {
302 what: "Usage past what is included",
303 free: "Not possible: a free workspace never runs up a bill",
304 plan: "Charged at cost plus 20%, up to a spend limit you set. No quotas: only your limit stops anything.",
305 },
306 ];
307}
308
309export default function Pricing({ loaderData }: Route.ComponentProps) {
310 const { book, free } = loaderData;
311 const checked = book?.prices.map((p) => p.checkedAt).filter((at): at is string => !!at).sort().at(-1);
312 const given = Object.fromEntries(Object.entries(book?.free ?? {}).filter(([, value]) => value != null));
313 const tier: Required<FreeTier> = { ...DEFAULT_FREE, ...given };
314 const plan = book?.plans?.find((p) => p.feature === "plan") ?? DEFAULT_PLAN;
315 const price = plan.monthlyCents / 100;
316 const dollars = wholeDollars;
317 // What g1t's own metered work is marked up, from the price book: one figure today.
318 const runMarkups = (book?.prices ?? [])
319 .filter((p) => !SHOWN_APART.has(p.meter) && p.meter !== "security_activation" && p.costMicros > 0)
320 .map((p) => p.markupPercent);
321 const markup = runMarkups.length && Math.min(...runMarkups) === Math.max(...runMarkups) ? `${runMarkups[0]}%` : "20%";
322 const modelMarkup = book?.modelMarginPercent ?? 0;
323 const agentRate = book?.prices.find((p) => p.meter === "agent_tokens");
324 const agentRateComing = book?.changes.find((c) => c.meter === "agent_tokens" && c.effectiveAt);
325 const agentRateLine =
326 agentRate && agentRate.priceMicros > 0
327 ? `${money(agentRate.priceMicros)} per million tokens`
328 : agentRateComing
329 ? `$0, and ${money(agentRateComing.newCostMicros)} per million tokens from ${agentRateComing.effectiveAt!.slice(0, 10)}`
330 : "as listed under Usage below";
331 // The summary tile: the rate in force, or the one coming and its day ("from Oct 22").
332 const comingDay = agentRateComing
333 ? new Date(agentRateComing.effectiveAt!).toLocaleDateString("en-US", { month: "short", day: "numeric", timeZone: "UTC" })
334 : null;
335 const agentRateTile =
336 agentRate && agentRate.priceMicros > 0
337 ? `${money(agentRate.priceMicros)} per million tokens`
338 : agentRateComing
339 ? `${money(agentRateComing.newCostMicros)} per million tokens from ${comingDay}`
340 : "Per million tokens";
341 return (
342 <main className="mx-auto max-w-4xl px-4 py-12">
343 <p className="text-sm font-medium text-accent">Pricing</p>
344 <h1 className="mt-2 text-3xl font-semibold tracking-tight sm:text-4xl">Models at cost. What g1t runs, at cost plus {markup}.</h1>
345 <p className="mt-3 max-w-2xl text-muted">
346 People chatting and the forge are free for everyone. Models are billed at the provider&apos;s price
347 {modelMarkup ? ` plus ${modelMarkup}%` : ", with no markup"}. The agent rate pays for what g1t runs around every model
348 call: the model gateway, secrets, routing, context and pass-through to your own provider, so it applies on your own
349 keys too. Everything else g1t runs is billed at what it costs g1t plus {markup}. Your own runners are free, and there
350 are no seats. The numbers on this page are the live price book g1t charges from. Prices exclude tax, which is added
351 where it applies.
352 </p>
353 <Card asChild tone="plain" className="mt-6 grid gap-px overflow-hidden bg-line text-sm sm:grid-cols-2 lg:grid-cols-5">
354 <ul>
355 {[
356 ["Models", modelMarkup ? `Provider price + ${modelMarkup}%` : "The provider's price", "No markup on tokens"],
357 ["Agent rate", agentRateTile, "Gateway, secrets, routing and pass-through, on your own keys too"],
358 ["Everything else g1t runs", `At cost + ${markup}`, "Sandboxes, builds, hosting, storage, search and scans"],
359 ["Your own runners", "Free", "Agents, checks and workflows on your hardware"],
360 ["People", "No seats", "Everyone in the workspace at one price"],
361 ].map(([what, price, about]) => (
362 <li key={what} className="bg-surface px-4 py-3">
363 <p className="text-xs text-muted">{what}</p>
364 <p className="mt-0.5 font-medium">{price}</p>
365 <p className="mt-0.5 text-xs text-faint">{about}</p>
366 </li>
367 ))}
368 </ul>
369 </Card>
370 {free && (
371 <div className="mt-5 rounded-xl border border-accent/30 bg-accent/5 px-4 py-3 text-sm">
372 <span className="font-medium">Free while g1t is being built out.</span>{" "}
373 <span className="text-muted">Usage is recorded at these prices but not charged for now. The plan is charged.</span>
374 </div>
375 )}
376
377 <section className="mt-10 rounded-xl border border-accent/40 bg-surface p-6">
378 <div className="flex flex-wrap items-baseline justify-between gap-3">
379 <h2 className="flex flex-wrap items-center gap-2 text-xl font-semibold tracking-tight">
380 {plan.title}
381 <span className="rounded-full bg-accent/15 px-2 py-0.5 text-xs font-medium tracking-normal text-accent">Recommended</span>
382 </h2>
383 <p>
384 <span className="text-3xl font-semibold tabular-nums">${price}</span>{" "}
385 <span className="text-sm text-muted">a month per workspace</span>
386 <span className="block text-right text-xs text-faint">
387 {plan.cardFeeCents ? `+ $${(plan.cardFeeCents / 100).toFixed(2)} card processing fee, plus tax where it applies` : "Plus tax where it applies"}
388 </span>
389 </p>
390 </div>
391 <p className="mt-2 text-sm text-muted">
392 The plan for a team whose agents do real work: unlimited members, agents, checks, the merge queue and
393 deployments.
394 </p>
395 <p className="mt-3 text-sm text-fg-soft">
396 One price for the whole team: a 10-person team pays ${price} a month, not ${price} a person.
397 </p>
398 <ul className="mt-4 space-y-1.5 text-sm text-muted">
399 {plan.includes.map((line) => (
400 <li key={line} className="flex gap-2">
401 <span aria-hidden className="text-accent">
402 ✓
403 </span>
404 {line}
405 </li>
406 ))}
407 </ul>
408 <p className="mt-3 text-xs text-faint">{plan.overage}</p>
409 <div className="mt-5 grid gap-5 border-t border-line pt-5 text-sm sm:grid-cols-2">
410 <div>
411 <p className="font-medium">Where the ${price} goes</p>
412 <p className="mt-1 text-muted">
413 $10 comes back to you as usage: agents, sandboxes, builds and deployments at cost plus 20%, used before
414 anything else. The other $10 pays for running g1t, the free forge for everyone, and the people building it.
415 </p>
416 </div>
417 <div>
418 <p className="font-medium">No quotas</p>
419 <p className="mt-1 text-muted">
420 No count of projects, previews, builds, requests or git operations ever stops a workspace on the plan. Past
421 the $10, usage is charged at cost plus 20%, and only your spend limit stops it. Unused included usage does
422 not roll over.
423 </p>
424 </div>
425 </div>
426 <p className="mt-5 text-sm text-muted">An owner starts the plan from the workspace's Billing page.</p>
427 </section>
428
429 <section id="workspace" className="mt-14">
430 <h2 className="text-xl font-semibold tracking-tight">Chat, Docs and agents</h2>
431 <p className="mt-1 max-w-3xl text-sm text-muted">
432 People talking costs g1t very little, so it is included. Agents use models, so they are charged for what they
433 use, to the agent that used it.
434 </p>
435 <Card tone="plain" className="mt-4 overflow-hidden">
436 <dl className="divide-y divide-line text-sm">
437 {WORKSPACE_CHARGES.map((row) => (
438 <div key={row.what} className="grid gap-1 px-4 py-3 sm:grid-cols-[14rem_1fr] sm:gap-4">
439 <dt className="font-medium">
440 {row.what}
441 {row.soon && (
442 <span className="ml-2 inline-block rounded bg-raised px-1.5 py-0.5 text-xs font-normal whitespace-nowrap text-muted">Coming soon</span>
443 )}
444 </dt>
445 <dd className="text-muted">{row.how}</dd>
446 </div>
447 ))}
448 </dl>
449 </Card>
450 <p className="mt-3 text-sm text-muted">
451 The agent rate today: {agentRateLine}. A chat reply is usually a few thousand tokens on a fast model, so most
452 replies cost a fraction of a cent. See{" "}
453 <a href="https://docs.g1t.sh/guides/agents/#what-an-agent-costs" className="text-accent hover:underline">
454 what an agent costs
455 </a>
456 .
457 </p>
458 </section>
459
460 <section id="spend-less" className="mt-14">
461 <h2 className="text-xl font-semibold tracking-tight">Help spending less</h2>
462 <p className="mt-1 max-w-3xl text-sm text-muted">Prices near cost are half of it. The other half is not spending more than the work needs.</p>
463 <div className="mt-4 grid gap-4 sm:grid-cols-3">
464 <Card asChild className="p-5">
465 <section>
466 <h3 className="font-medium">Effort per agent</h3>
467 <p className="mt-1.5 text-sm text-muted">
468 Auto, Low, Medium, High or Max: how hard an agent works, from the model tier it starts on to how hard it reasons and how
469 many steps a session takes. Each level shows what a typical task has cost that agent.
470 </p>
471 </section>
472 </Card>
473 <Card asChild className="p-5">
474 <section>
475 <h3 className="font-medium">Suggestions checked against your work</h3>
476 <p className="mt-1.5 text-sm text-muted">
477 Every week, each agent&apos;s finished sessions are checked. A cheaper level is suggested only when its work was accepted
478 as often, with the numbers it rests on and an Apply button. With too little history, Spend says so instead.
479 </p>
480 </section>
481 </Card>
482 <Card asChild className="p-5">
483 <section>
484 <h3 className="font-medium">Budgets that hold</h3>
485 <p className="mt-1.5 text-sm text-muted">
486 Workspace, team, person, agent and task budgets are checked before work starts. An agent at its budget stops taking new
487 work and says so.
488 </p>
489 </section>
490 </Card>
491 </div>
492 </section>
493
494 <h2 className="mt-14 text-xl font-semibold tracking-tight">Free and the plan, side by side</h2>
495 <p className="mt-1 text-sm text-muted">
496 Secret scanning, push protection, vulnerability alerts and security updates are free everywhere, on every plan.
497 </p>
498 {/* On a phone, one row at a time with both answers under it; a table that wide would scroll. */}
499 <Card asChild tone="plain" divided className="mt-4 text-sm sm:hidden">
500 <ul>
501 {rows(tier).map((row) => (
502 <li key={row.what} className="px-4 py-3">
503 <p className="font-medium">{row.what}</p>
504 {row.note && <p className="text-xs text-faint">{row.note}</p>}
505 <dl className="mt-2 grid grid-cols-[4.5rem_1fr] gap-x-3 gap-y-1.5">
506 <dt className="text-xs leading-5 text-faint">Free</dt>
507 <dd className="text-muted">{row.free}</dd>
508 <dt className="text-xs leading-5 text-faint">{plan.title}</dt>
509 <dd className="text-muted">{row.plan}</dd>
510 </dl>
511 </li>
512 ))}
513 </ul>
514 </Card>
515 <Card tone="plain" className="mt-4 hidden overflow-x-auto sm:block">
516 <table className="w-full min-w-[36rem] text-left text-sm">
517 <thead className="border-b border-line text-xs text-muted">
518 <tr>
519 <th className="px-4 py-2.5 font-medium">
520 <span className="sr-only">What</span>
521 </th>
522 <th className="px-4 py-2.5 font-medium">Free</th>
523 <th className="px-4 py-2.5 font-medium">
524 {plan.title}, ${price} a month
525 </th>
526 </tr>
527 </thead>
528 <tbody className="divide-y divide-line">
529 {rows(tier).map((row) => (
530 <tr key={row.what} className="align-top">
531 <td className="px-4 py-3">
532 <p className="font-medium">{row.what}</p>
533 {row.note && <p className="text-xs text-faint">{row.note}</p>}
534 </td>
535 <td className="px-4 py-3 text-muted">{row.free}</td>
536 <td className="px-4 py-3 text-muted">{row.plan}</td>
537 </tr>
538 ))}
539 </tbody>
540 </table>
541 </Card>
542 <p className="mt-3 text-sm text-muted">
543 Git operations cost g1t money too: Cloudflare charges g1t $0.15 per 1,000. {count(tier.gitOperationsIncluded)} a
544 month is far more than an active workspace uses; an agent run takes two to four.
545 </p>
546
547 <h2 className="mt-14 text-xl font-semibold tracking-tight">No card, no compute</h2>
548 <div className="mt-3 max-w-3xl space-y-3 text-sm text-muted">
549 <p>
550 Agents, checks, workflows, the merge queue, deployments and semantic search run on g1t's machines. They need
551 the plan, or a card check.
552 </p>
553 <p>
554 The reason: compute costs g1t real money from the first second, and free compute draws people who use it to
555 mine cryptocurrency. A card check is the smallest gate that stops that, with one trial per card.
556 </p>
557 <p>
558 A card check is never charged. Stripe saves and verifies the card, with 3-D Secure where your bank asks for it.
559 Nothing is charged until an owner starts the plan, and then the same card is used, without asking for it again.
560 The trial needs a credit or debit card; prepaid cards can still pay for the plan.
561 </p>
562 </div>
563
564 <div className="mt-5 grid gap-4 sm:grid-cols-2">
565 <Card asChild className="p-5">
566 <section>
567 <h3 className="font-medium">The trial</h3>
568 <p className="mt-1.5 text-sm text-muted">
569 {dollars(tier.trialWorkspaceMicros)} of usage, once per workspace and once per card, after a card check with a credit or
570 debit card. It comes from a{" "}
571 {dollars(tier.trialMonthlyPoolMicros)} pool each month for everyone; when a month's pool is given out, new
572 trials wait until the 1st. The trial does not cover deployments and never turns into a charge. If the last
573 run on a trial goes past it, g1t covers the difference.
574 </p>
575 </section>
576 </Card>
577 <Card asChild className="p-5">
578 <section>
579 <h3 className="font-medium">The open-source pool</h3>
580 <p className="mt-1.5 text-sm text-muted">
581 Checks, workflows and the merge queue on public repositories, after a card check:{" "}
582 {dollars(tier.ossPoolMicros)} a month in all, up to {dollars(tier.ossRepoMicros)} a month per repository.
583 Agents do not run from the pool. When the pool or a repository's share is used up, the work waits for the
584 month to turn, or the workspace pays as usual.
585 </p>
586 </section>
587 </Card>
588 </div>
589
590 <h2 className="mt-14 text-xl font-semibold tracking-tight">Limits, and how to raise them</h2>
591 <p className="mt-1 max-w-3xl text-sm text-muted">
592 g1t lets usage run ahead of payment only so far. Limits keep a mistake small, for you and for g1t.
593 </p>
594 <ul className="mt-4 grid gap-3 text-sm sm:grid-cols-2">
595 <Card asChild className="p-4">
596 <li>
597 <p className="font-medium">{dollars(tier.paidStartCeilingMicros)} in the first month</p>
598 <p className="mt-1 text-muted">
599 A workspace on the plan can use up to {dollars(tier.paidStartCeilingMicros)} in its first month. After that,
600 the limit grows with payments that clear.
601 </p>
602 </li>
603 </Card>
604 <Card asChild className="p-4">
605 <li>
606 <p className="font-medium">Your own spend limit</p>
607 <p className="mt-1 text-muted">
608 Owners set a monthly spend limit anywhere up to the highest limit the workspace has had, with no approval.
609 Once, you can raise it yourself to twice that.
610 </p>
611 </li>
612 </Card>
613 <Card asChild className="p-4">
614 <li>
615 <p className="font-medium">Prepay to raise it now</p>
616 <p className="mt-1 text-muted">
617 Prepaying from $25 raises what you can use by the same amount, at once. From $1,000 you can also pay by bank
618 transfer.
619 </p>
620 </li>
621 </Card>
622 <Card asChild className="p-4">
623 <li>
624 <p className="font-medium">Raise my limit</p>
625 <p className="mt-1 text-muted">
626 Need more? Ask from Billing with the amount, why, and what you expect to spend. You get an answer within one
627 business day, in the app and by email.
628 </p>
629 </li>
630 </Card>
631 </ul>
632
633 <h2 className="mt-14 text-xl font-semibold tracking-tight">When usage runs high</h2>
634 <ul className="mt-4 grid gap-3 text-sm sm:grid-cols-2">
635 <Card asChild className="p-4">
636 <li>
637 <p className="font-medium">A spike pauses new work</p>
638 <p className="mt-1 text-muted">
639 When an hour's spend is five times your usual hour, and at least $5, new compute waits for an owner to choose
640 Keep going or Stop. Runs already going finish.
641 </p>
642 </li>
643 </Card>
644 <Card asChild className="p-4">
645 <li>
646 <p className="font-medium">Caps per run and per issue</p>
647 <p className="mt-1 text-muted">
648 One agent run stops at $2 and the agents on one issue at $10 in all, so a run stuck in a loop stops on its own.
649 Owners change both on Billing.
650 </p>
651 </li>
652 </Card>
653 <Card asChild className="p-4">
654 <li>
655 <p className="font-medium">Alerts at 50, 75, 90 and 100%</p>
656 <p className="mt-1 text-muted">
657 Of the plan's included usage, your spend limit and g1t's limit: in the app and by email.
658 </p>
659 </li>
660 </Card>
661 <Card asChild className="p-4">
662 <li>
663 <p className="font-medium">Spent more than you meant to? Tell us</p>
664 <p className="mt-1 text-muted">
665 Tell us from Billing what happened. Once in 12 months, g1t can credit back usage you did not mean, always
666 including its 20% on it. Larger credits, or a second one within 12 months, are reviewed by a person.
667 </p>
668 </li>
669 </Card>
670 </ul>
671 <p className="mt-3 text-sm text-muted">
672 No card is charged less than {dollars(tier.minChargeMicros)} when a month closes, so a payment's fee is never most
673 of it. Smaller amounts carry over to the next invoice. Charges at a limit always go through.
674 </p>
675
676 <div className="mt-14 grid gap-4 sm:grid-cols-2">
677 {HOW.map((item) => (
678 <Card asChild key={item.title} className="p-5">
679 <section>
680 <h2 className="font-medium">{item.title}</h2>
681 <p className="mt-1.5 text-sm text-muted">{item.body}</p>
682 </section>
683 </Card>
684 ))}
685 </div>
686
687 <h2 className="mt-14 text-xl font-semibold tracking-tight">Usage</h2>
688 <p className="mt-1 text-sm text-muted">
689 {checked ? (
690 <>
691 Last checked against Cloudflare's bill <TimeAgo at={checked} />.
692 </>
693 ) : (
694 "Starting from Cloudflare's published prices; checked against its bill daily."
695 )}
696 </p>
697 <Card tone="plain" className="mt-4 overflow-x-auto">
698 <table className="w-full text-left text-sm sm:min-w-[36rem]">
699 <thead className="border-b border-line text-xs text-muted">
700 <tr>
701 <th className="px-4 py-2.5 font-medium">What</th>
702 <th className="px-4 py-2.5 font-medium">Costs g1t</th>
703 {/* The markup is in what you pay; on a phone the column gives way. */}
704 <th className="hidden px-4 py-2.5 font-medium sm:table-cell">Markup</th>
705 <th className="px-4 py-2.5 font-medium">You pay</th>
706 </tr>
707 </thead>
708 <tbody className="divide-y divide-line">
709 <tr>
710 <td className="px-4 py-3">
711 <p className="font-medium">Agent models</p>
712 <p className="text-xs text-faint">g1t's hosted models for agent runs, the cheapest that can do each job, paid from AI credit</p>
713 </td>
714 <td className="px-4 py-3 text-muted">What the provider charges, per request</td>
715 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">{book?.modelMarginPercent ?? 0}%</td>
716 <td className="px-4 py-3 text-muted">{book?.modelMarginPercent ? `Cost + ${book.modelMarginPercent}%` : "The provider's price"}</td>
717 </tr>
718 {(() => {
719 const rate = book?.prices.find((p) => p.meter === "agent_tokens");
720 const gateway = book?.prices.find((p) => p.meter === "gateway_models");
721 const feePercent = book?.prices.find((p) => p.meter === "card_fee_percent");
722 const feeFixed = book?.prices.find((p) => p.meter === "card_fee_fixed");
723 const coming = book?.changes.find((c) => c.meter === "agent_tokens" && c.effectiveAt);
724 const ownRate = book?.prices.find((p) => p.meter === "agent_tokens_own");
725 const ownComing = book?.changes.find((c) => c.meter === "agent_tokens_own" && c.effectiveAt);
726 return (
727 <>
728 <tr>
729 <td className="px-4 py-3">
730 <p className="font-medium">g1t agent rate</p>
731 <p className="text-xs text-faint">The model gateway, secrets, routing, context and pass-through, on every token an agent run uses</p>
732 <p className="text-xs text-faint">Tokens count by kind: {tokenWeights(book?.prices ?? [])}</p>
733 </td>
734 <td className="px-4 py-3 text-muted">A flat rate</td>
735 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">—</td>
736 <td className="px-4 py-3 font-mono text-xs tabular-nums">
737 {rate && rate.priceMicros > 0 ? `${money(rate.priceMicros)} per million tokens` : coming ? `${money(coming.newCostMicros)} per million tokens from ${coming.effectiveAt!.slice(0, 10)}` : "$0.25 per million tokens"}
738 </td>
739 </tr>
740 <tr>
741 <td className="px-4 py-3">
742 <p className="font-medium">g1t agent rate, your own model key</p>
743 <p className="text-xs text-faint">The same, on runs that pass through to your own provider; its models are billed by your provider, not g1t</p>
744 </td>
745 <td className="px-4 py-3 text-muted">A flat rate</td>
746 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">—</td>
747 <td className="px-4 py-3 font-mono text-xs tabular-nums">
748 {ownRate && ownRate.priceMicros > 0 ? `${money(ownRate.priceMicros)} per million tokens` : ownComing ? `${money(ownComing.newCostMicros)} per million tokens from ${ownComing.effectiveAt!.slice(0, 10)}` : "$0.25 per million tokens"}
749 </td>
750 </tr>
751 <tr>
752 <td className="px-4 py-3">
753 <p className="font-medium">
754 AI Gateway <span className="ml-1 rounded bg-accent/15 px-1.5 py-0.5 text-xs text-accent">Free during beta</span>
755 </p>
756 <p className="text-xs text-faint">Your own code calling Claude and open models through g1t, in Anthropic's or OpenAI's format, paid from AI credit; on your own providers, free</p>
757 </td>
758 <td className="px-4 py-3 text-muted">What the provider charges</td>
759 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">{gateway?.markupPercent ?? 0}%</td>
760 <td className="px-4 py-3 text-muted">{gateway?.markupPercent ? `Cost + ${gateway.markupPercent}%` : "The provider's price"}</td>
761 </tr>
762 {feePercent && feeFixed && (
763 <tr>
764 <td className="px-4 py-3">
765 <p className="font-medium">Card processing fee</p>
766 <p className="text-xs text-faint">
767 On every card payment, as its own line shown before you pay; never on bank transfers or invoiced billing
768 </p>
769 </td>
770 <td className="px-4 py-3 text-muted">Stripe's fee</td>
771 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">—</td>
772 <td className="px-4 py-3 font-mono text-xs tabular-nums">
773 {(feePercent.priceMicros / 10_000).toFixed(1)}% + {money(feeFixed.priceMicros)}
774 </td>
775 </tr>
776 )}
777 </>
778 );
779 })()}
780 <tr>
781 <td className="px-4 py-3">
782 <p className="font-medium">Your own runners</p>
783 <p className="text-xs text-faint">Agents, checks and workflows on your own hardware</p>
784 </td>
785 <td className="px-4 py-3 text-muted">Nothing</td>
786 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">—</td>
787 <td className="px-4 py-3 text-muted">Free</td>
788 </tr>
789 <tr>
790 <td className="px-4 py-3">
791 <p className="font-medium">Projects, previews and apps</p>
792 <p className="text-xs text-faint">Having them. An app's requests and CPU time are charged below.</p>
793 </td>
794 <td className="px-4 py-3 text-muted">Next to nothing</td>
795 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">—</td>
796 <td className="px-4 py-3 text-muted">Not charged</td>
797 </tr>
798 {(book?.prices ?? []).filter((price) => !SHOWN_APART.has(price.meter)).map((price) => (
799 <tr key={price.meter}>
800 <td className="px-4 py-3">
801 <p className="font-medium">{price.title}</p>
802 <p className="text-xs text-faint">
803 {price.meter === "actions_cache" ? "On the plan only. A free workspace is never charged for it. " : ""}
804 {price.source === "cloudflare" ? "Measured from Cloudflare's bill" : "Cloudflare's published price"}
805 </p>
806 </td>
807 <td className="px-4 py-3 font-mono text-xs tabular-nums text-muted">{perUnit(price, price.costMicros)}</td>
808 <td className="hidden px-4 py-3 tabular-nums sm:table-cell">{price.markupPercent}%</td>
809 <td className="px-4 py-3 font-mono text-xs tabular-nums">{perUnit(price, price.priceMicros)}</td>
810 </tr>
811 ))}
812 </tbody>
813 </table>
814 </Card>
815
816 <h2 className="mt-14 text-xl font-semibold tracking-tight">Enterprise</h2>
817 <p className="mt-1 text-sm text-muted">
818 For organizations with several workspaces: one invoice and one limit. The prices are the ones on this page.
819 </p>
820 <Card asChild className="mt-4 p-5">
821 <section>
822 <ul className="grid gap-3 text-sm sm:grid-cols-2">
823 <li>
824 <p className="font-medium">Consolidated invoicing</p>
825 <p className="text-muted">One monthly invoice for every workspace, paid by card or bank transfer.</p>
826 </li>
827 <li>
828 <p className="font-medium">Custom terms</p>
829 <p className="text-muted">One limit across every workspace, invoice terms and a billing contact, set with you.</p>
830 </li>
831 <li>
832 <p className="font-medium">Security on every plan</p>
833 <p className="text-muted">
834 The audit log with export, {tier.planAuditRetentionDays} days or longer by arrangement, and secret push
835 protection, for every workspace.
836 </p>
837 </li>
838 <li>
839 <p className="font-medium">
840 Single sign-on <span className="ml-1 rounded bg-raised px-1.5 py-0.5 text-xs text-muted">Coming</span>
841 </p>
842 <p className="text-muted">Through your identity provider, on every plan once it is built. Not available yet.</p>
843 </li>
844 </ul>
845 <a
846 href={ENTERPRISE_MAIL}
847 className="mt-5 inline-flex items-center gap-1.5 rounded-md border border-line px-3 py-1.5 text-sm hover:border-line-strong"
848 >
849 Write to us about enterprise
850 <ArrowUpRight size={14} />
851 </a>
852 </section>
853 </Card>
854
855 <h2 className="mt-14 text-xl font-semibold tracking-tight">Price changes</h2>
856 {book && book.changes.length > 0 ? (
857 <Card asChild tone="plain" divided className="mt-4">
858 <ul>
859 {book.changes.map((change) => {
860 const title = book.prices.find((p) => p.meter === change.meter)?.title ?? change.meter;
861 // What you pay moved: the cost, the markup, or both.
862 const before = change.oldCostMicros * (100 + (change.oldMarkupPercent ?? change.markupPercent));
863 const after = change.newCostMicros * (100 + change.markupPercent);
864 const up = after > before;
865 const fresh = after === before || before === 0;
866 return (
867 <li key={`${change.meter}-${change.createdAt}`} className="px-4 py-3 text-sm">
868 <p>
869 <span className="font-medium">{title}</span>{" "}
870 {fresh ? (
871 <span className="text-muted">new</span>
872 ) : (
873 <span className={up ? "text-warn" : "text-accent"}>
874 {up ? "up" : "down"} {Math.abs((after / before - 1) * 100).toFixed(1)}%
875 </span>
876 )}
877 </p>
878 <p className="mt-0.5 text-xs text-faint">
879 {change.effectiveAt ? (
880 <>
881 {change.reason} · <span className="text-fg-soft">takes effect {change.effectiveAt.slice(0, 10)}</span>
882 </>
883 ) : (
884 <>
885 {change.reason} · <TimeAgo at={change.createdAt} />
886 </>
887 )}
888 </p>
889 </li>
890 );
891 })}
892 </ul>
893 </Card>
894 ) : (
895 <p className="mt-2 text-sm text-muted">None yet. When a price moves, it is listed here with why.</p>
896 )}
897
898 <h2 id="faq" className="mt-14 text-xl font-semibold tracking-tight">Questions</h2>
899 <Card asChild tone="plain" divided className="mt-4">
900 <dl>
901 {FAQ.map((item) => (
902 <div key={item.q} className="px-4 py-4 text-sm">
903 <dt className="font-medium">{item.q}</dt>
904 <dd className="mt-1.5 text-muted">{item.a}</dd>
905 </div>
906 ))}
907 </dl>
908 </Card>
909
910 <a
911 href="https://docs.g1t.sh/guides/usage-and-billing/"
912 className="mt-12 inline-flex items-center gap-1.5 text-sm text-accent hover:underline"
913 >
914 How usage and billing work
915 <ArrowUpRight size={14} />
916 </a>
917 </main>
918 );
919}