Skip to content

Commit

The docs folder is gone, and what it held lives where people read it: how a self-hosted g1t runs and how to deploy g1t to Cloudflare are pages on docs.g1t.sh under Run g1t yourself, and speed, rate limits and operating g1t.sh are sections of CONTRIBUTING.md; code that cited a file in docs/ now points to the page or section that covers it, or says what it means itself, and applied migrations and the runner images are left as they were.

syntaqxcommitted Parentc5b604bBrowse files
188 files+764−1380/188 viewed
+3−3
11 # Deploys g1t.sh from main, with g1t's own Actions. What it does is
2−# scripts/deploy.mjs, the same tool a person runs; docs/DEPLOYING.md is the
3−# guide.
2+# scripts/deploy.mjs, the same tool a person runs; the guide is
3+# docs.g1t.sh/guides/deploy-to-cloudflare/.
44 #
55 # check the deploy manifest is consistent, and the tool's tests pass
66 # plan what changed since each Worker's live commit, and pending migrations
2727 # so with its own Docker Engine, on a larger machine. Optionally, the
2828 # secret STATUS_DEPLOY_TOKEN (the status Worker's secret of the same name)
2929 # and status.g1t.sh among the same workflow-only domains, so status.g1t.sh
30−# hears each deploy start and finish. See docs/DEPLOYING.md.
30+# hears each deploy start and finish.
3131 name: Deploy
3232
3333 on:
+2−1
1515 #
1616 # node scripts/deploy.mjs build-base
1717 #
18−# and commit services/runner/base.json. docs/DEPLOYING.md explains both.
18+# and commit services/runner/base.json. "The runner's images" in
19+# docs.g1t.sh/guides/deploy-to-cloudflare/ explains both.
1920 # Once a runner is registered, set the repository variable
2021 # RUNNER_BASE_SELF_HOSTED to "true" to turn this workflow's job on.
2122 name: Runner base image
+2−2
55 #
66 # A release is a tag `runner-v<version>`, where the version is the one in
77 # crates/runner/Cargo.toml; or run it by hand. scripts/runner-release.mjs
8−# does the work; docs/DEPLOYING.md, "The self-hosted runner", says how to
9−# make the release key the first time.
8+# does the work, and its header says how to make the release key the first
9+# time; CONTRIBUTING.md ("Deploying") says how a release is made.
1010 name: Runner release
1111
1212 on:
+64−3
5858 Pushes to `main` deploy themselves: `.g1t/workflows/deploy.yml` runs
5959 `scripts/deploy.mjs`, which deploys only the parts that changed, migrations
6060 first. Every deployable part is listed in `deploy/stack.jsonc`; a new service
61−or app goes there (`npm run test:deploy` says what is missing). See
62−[docs/DEPLOYING.md](docs/DEPLOYING.md) for the tool, the workflow, rollbacks
63−and adding a service.
61+or app goes there, and in the table on
62+[How a self-hosted g1t runs](https://docs.g1t.sh/guides/self-hosting-architecture/#each-part)
63+(`npm run test:deploy` says what is missing).
64+[Deploy g1t to Cloudflare](https://docs.g1t.sh/guides/deploy-to-cloudflare/)
65+covers the tool, the workflow, rollbacks, adding a unit and first-time
66+setup.
67+
68+- **Migrations run before the code**, so the old code reads the new schema
69+ for a minute or more. Add tables and columns; change what rows mean in
70+ two deploys (code that reads both forms first); never drop what live code
71+ still reads.
72+- **The self-hosted runner** is released, not deployed: bump `version` in
73+ `crates/runner/Cargo.toml`, merge, and push a `runner-v<version>` tag.
74+ `.g1t/workflows/runner-release.yml` builds, signs and publishes it, and
75+ runners update themselves to it. `scripts/runner-release.mjs` does the
76+ same by hand.
77+
78+## Speed
79+
80+Pages are a few rounds of service calls, and each round costs a trip to
81+the databases, so start calls together and add no rounds.
82+
83+- Every page answers with `Server-Timing`: each loader, each service's
84+ calls and their database time. Look at it in DevTools when a page feels
85+ slow.
86+- `scripts/perf/measure.ps1` times pages from your machine (`-BrowserUA`
87+ for signed-out pages as a browser sees them). A page that only reads
88+ must not set the `g1t_d1` cookie: a new read-only service method goes in
89+ `READS` in `apps/web/app/lib/perf.ts`.
90+- Targets from the US: signed-out pages under 200 ms to first byte,
91+ signed-in pages under 400 ms, streamed panels within a second.
92+- Workers run without Smart Placement; `scripts/perf/placement-probe.mjs`
93+ measures a placement before you pin one.
94+
95+## Rate limits
96+
97+`RATE_LIMITS` in `packages/contracts/src/rate-limits.ts` is the table of
98+record, and the [rate limits page](https://docs.g1t.sh/reference/rate-limits/)
99+is the public one: change both, and the binding in the Worker's
100+`wrangler.jsonc`, together (`front-door-limits.test.ts` fails when they
101+disagree). Limits fail open, keys hash anything secret, and each Worker
102+takes its namespace ids from its own block of a hundred (41xx packages,
103+42xx web, 43xx repos, 44xx api, 45xx og, 46xx status).
104+
105+## Operating g1t.sh
106+
107+For Flagon staff.
108+
109+- **Incidents** are declared, updated and resolved in sudo, under
110+ **Platform → Incidents**, and appear on status.g1t.sh within 30 seconds.
111+ Declare as soon as people are affected, and pick the higher severity
112+ when unsure. SEV1 (down for most people, or data at risk) gets an update
113+ at least every 30 minutes and SEV2 (a core part broken for many) at least
114+ hourly; both email subscribers and need a blameless postmortem within
115+ five working days.
116+- **An Artifacts outage:** `scripts/ops/artifacts-namespaces.mjs` shows a
117+ failing namespace. After 15 minutes, serve it read-only from the fallback
118+ git store (`scripts/ops/restore-to-gitstore.mjs restore`, then the repos
119+ Worker's secret `GIT_FALLBACK_NAMESPACES`) and open an incident. To
120+ switch back, `reconcile` anything the fallback took, then delete the
121+ secret. The script's header has every step.
122+- **Costs and margin**, model prices, credits and the platform pause are
123+ in sudo, under **Costs & margin**. The code is in `services/billing/src`
124+ (`costs.rs`, `margin.rs`, `pricing.rs`, `budget.rs`, `platform.rs`).
+5−4
1919 unfinished.
2020 - **Coming**: planned, not built.
2121
22−The plan behind this is [docs/PLAN.md](docs/PLAN.md).
23−
2422 ## Where things are
2523
2624 - Site: <https://g1t.sh>
2725 - Docs: <https://docs.g1t.sh>
2826 - API: <https://api.g1t.sh> · MCP: <https://mcp.g1t.sh>
29−- Plan: [docs/PLAN.md](docs/PLAN.md)
3027 - Limits you can hit today: [docs.g1t.sh/about/limitations](https://docs.g1t.sh/about/limitations/)
3128
3229 ## What's in it
171168 http://localhost:8789; packages and container images are kept in the
172169 bundled S3-compatible store, RustFS. Agents, deployments and context search
173170 are off in this version.
174−[docs/SELF_HOSTING.md](docs/SELF_HOSTING.md) says what works and what is next.
171+[Run g1t yourself](https://docs.g1t.sh/guides/self-hosting/) says what works,
172+and [how a self-hosted g1t runs](https://docs.g1t.sh/guides/self-hosting-architecture/)
173+what runs inside it.
175174
176175 ### On Cloudflare
177176
208207
209208 Create the first account by registering on your site, or with
210209 `node services/identity/scripts/create-user.mjs <username>`.
210+[Deploy g1t to Cloudflare](https://docs.g1t.sh/guides/deploy-to-cloudflare/)
211+covers the deploy tool, the workflow and first-time setup in full.
211212
212213 ## License
213214
+1−1
1919 form_urlencoded = "1"
2020
2121 # wasm-opt at -O1: about the same gzipped size as -O in a tenth of the
22−# time (docs/DEPLOYING.md, "Build speed").
22+# time.
2323 [package.metadata.wasm-pack.profile.release]
2424 wasm-opt = ["-O1"]
+1−1
11 //! Artifacts over REST and MCP: a workspace's docs, slides, designs and
2−//! dashboards (Artifacts mode, docs/ARTIFACTS_MODE.md), at
2+//! dashboards (Artifacts mode), at
33 //! `/workspaces/{workspace}/artifacts` and as the `artifact` MCP tool.
44 //! Code calls them folios; people, URLs, the tool and the scopes say
55 //! "artifact". Workflow runs' artifacts are something else (artifacts.rs).
+2−1
1616 //! private key in PEM (PKCS#8 or PKCS#1). `ACTIONS_OIDC_KEY_PREVIOUS`,
1717 //! while it is set, is published too, so tokens it signed still verify
1818 //! while the new key takes over. Each key's `kid` is its RFC 7638
19−//! thumbprint. docs/DEPLOYING.md says how to make and rotate them.
19+//! thumbprint. docs.g1t.sh/guides/deploy-to-cloudflare/ ("OIDC tokens
20+//! for workflow jobs") says how to make and rotate them.
2021
2122 use base64::Engine;
2223 use base64::engine::general_purpose::{STANDARD, URL_SAFE_NO_PAD};
+8−1
171171 { label: 'Audit log', slug: 'guides/audit-log' },
172172 { label: 'Usage and billing', slug: 'guides/usage-and-billing' },
173173 { label: 'Git', slug: 'guides/git' },
174− { label: 'Run g1t yourself', slug: 'guides/self-hosting' },
175174 ],
176175 },
177176 {
177+ label: 'Run g1t yourself',
178+ items: [
179+ { label: 'With Docker Compose', slug: 'guides/self-hosting' },
180+ { label: 'How a self-hosted g1t runs', slug: 'guides/self-hosting-architecture' },
181+ { label: 'Deploy to Cloudflare', slug: 'guides/deploy-to-cloudflare' },
182+ ],
183+ },
184+ {
178185 label: 'Reference',
179186 items: [
180187 { label: 'API overview', slug: 'reference/api' },
+8−6
106106 fast and still strictly correct.
107107
108108 <Aside type="note" title="Where this stands today">
109−Rules 1, 2, 3, 5, 6 and 7 hold today. Replies look up code, issues, pull
110−requests and messages only within the conversation's audience, a withheld
111−read says nothing about what was withheld, and every lookup is recorded.
112−Public channels and conversations of more than 50 people get no code reads
113−at all for now, the strictest reading of rule 2. Memory with its source
114−(rule 4) comes with agent memory. <Soon />
109+Replies and sessions look up code, issues, pull requests, messages and
110+artifacts only within the conversation's audience, a withheld read says
111+nothing about what was withheld, and every lookup is recorded. Public
112+channels and conversations of more than 50 people get no code reads at
113+all for now, the strictest reading of rule 2. Every fact an agent keeps
114+records its source and is recalled only where that source allows; see
115+[agent memory](/guides/agent-memory/#scopes). Files, and the rules for
116+customer-data files, are <Soon />
115117 </Aside>
116118
117119 ## A support lead asks for a change
+3−1
3333 | **An issue is opened** | By a person or an agent. |
3434 | **A deploy fails** | A production or preview deploy. |
3535
36−Each run is one session about the one thing that happened. Name the
36+Each run is one session about the one thing that happened, and a routine
37+runs at most 20 times an hour on events; events past that are skipped, so
38+a burst can't run up the agent's budget. Name the
3739 **repositories** to follow, such as `acme/web, acme/api` (up to 20), or
3840 leave it empty for every repository the routine's sponsor can read.
3941
+5−4
153153
154154 ## Issues for whoever asked
155155
156−When a session finds work to do in code, it files issues in a repository
157−the asker can read, on their behalf, and lists them under **What it
158−produced**. Someone who can't change code still gets the issue filed;
159−changes come from people, and agents, who may make them.
156+When a session finds work to do in code, it drafts an issue for a
157+repository the asker can read. The draft is posted in the conversation as
158+a card with **File issue** and **Discard**: whoever presses **File issue**
159+files it as themselves, if they can read the repository. The agent never
160+files it on its own. See [cards you can act on](/guides/chat/#cards-you-can-act-on).
160161
161162 ## Next
162163
+18−8
4949 | --- | --- |
5050 | **In every workspace** | On every surface: Chat, issues and pull requests, Notifications and MCP. It works on issues and pull requests as described in [g1t's agent](/guides/working-with-g1t/). |
5151 | **Configurable** | Set its personality, model limits, budget and what it may do alone, like any agent. Its job is fixed, and you can add instructions to it. |
52−| **Knows the team** <Soon /> | Every colleague's role, what they are working on and their budget, and which teams own what. |
52+| **Knows the team** | Every agent you hire: its handle, title, team, responsibilities, whether it is idle, working, paused or out of budget, and its spend this month against its monthly cap. |
5353 | **Delegates** | When a specialist's role fits, it [hands the work off](#hand-off) with a brief: here, if the specialist is in the conversation, or in a group message with you and them. At most two hand-offs per message. |
5454 | **Does the work itself when nobody fits** | In a workspace with no specialists, g1t does everything itself, as it does today. |
55−| **Reports** <Soon /> | A daily or weekly summary of what the team's agents did, and answers to "what's everyone working on?" |
55+| **Reports** | Answers "what's everyone working on?" from what it knows of the team. A daily or weekly summary of what the team's agents did is <Soon /> |
5656
5757 `g1t` is never another agent's handle.
5858
8181
8282 </Steps>
8383
84−The agent appears on the Agents page as **Idle**. Open a DM with it from
85−Chat's **New message**, or invite it to the channels its team works in.
84+The agent appears on the Agents page as **Idle**, and a direct message
85+between you and it opens in Chat, where it says hello in its own voice: who
86+it is, what it will do for the team, and a thing or two to ask it first.
87+That hello is a reply like any other, charged to its budget; when the
88+workspace has no model it can use, it sends a short fixed hello instead.
89+Invite it to the channels its team works in.
8690
8791 ### Example: hire Margo from the QA template
8892
140144 | Responsibilities | What it answers for, one per line. | 2 to 8, each up to 160 characters, or none yet. |
141145 | Job | Its instructions: how it works and what good looks like. | Up to 8,000 characters. |
142146 | Personality | A preset, plus free text that refines the voice. | Free text up to 1,000 characters. |
143−| Subagents | Help it keeps for its own work. See [subagents](#subagents). | Run soon. |
147+| Subagents | Help it keeps for its own work. See [subagents](#subagents). | Up to 8. They run inside its sessions. |
148+| Required reading | Spaces in [Artifacts](/guides/artifacts/) it checks first, every time it answers or works. It still reads only what the person it works for, and everyone reading its answer, can open. | Up to 10 spaces. |
144149 | Models | A floor, a ceiling and the providers it may use. | See [model routing](#model-routing). |
145150 | Budget | A monthly cap, a daily cap and a cap per session. | Each optional, up to $100,000. |
146151 | What it may do alone | Pull requests, merging, production deploys, doc edits. | See [what it may do alone](#what-it-may-do-alone). |
374379 While it writes, the agent shows as typing. Its answer is charged to its
375380 own budget; see [what an agent costs](#what-an-agent-costs).
376381
377−<Aside type="note" title="What a reply can see today">
382+<Aside type="note" title="What a reply can see">
378383 A reply reads the conversation it is in: the thread, or the latest 30
379384 messages of the channel or DM. It knows who asked and whether they can
380−change code. Looking things up in code, issues, checks and docs while it
381−answers is <Soon />
385+change code, and it is given the facts it [remembers](/guides/agent-memory/)
386+for that place and the passages of [artifacts](/guides/artifacts/#agents-and-artifacts)
387+closest to what was asked. While it answers it can look up code, issues,
388+pull requests with their checks, earlier messages and artifacts, up to 8
389+lookups a reply, only within what everyone in the conversation can see.
390+In public channels and conversations of more than 50 people it reads no
391+code. See [what agents can do for whom](/guides/agent-access/).
382392 </Aside>
383393
384394 ## Model routing
+7−3
1313 for can read.
1414
1515 Open **Artifacts** in the dock on the left, or go to
16−`g1t.sh/<workspace>/-/artifacts`. Artifacts is open to every member of a
17−workspace, on every plan.
16+`g1t.sh/<workspace>/-/artifacts`. On a phone, it's under **More** in the bar
17+at the bottom. Artifacts is open to every member of a workspace, on every
18+plan.
1819
1920 ## How it fits together
2021
4243 - **Filters** narrow the list by kind, space, owner and project. On a phone
4344 they're under **Filters**.
4445 - The list and grid buttons switch between rows and cards with a preview.
46+ On a phone, Home shows the list, and the sidebar's sections follow it.
4547 - Each row shows the kind, who can open it (a lock when only you can, a globe
4648 when the workspace can, a link when anyone in it with the link can, or how
4749 many people it's shared with), where it is, and when it was last edited and
201203 pushed to the default branch, the doc is marked **possibly out of date**: a
202204 banner on it, a dot in the sidebar, and **Possibly out of date** in the
203205 sidebar listing every such doc you can open. Its owner is told. Read what
204−changed, update it (or ask an agent to), then press **It's current**.
206+changed, update it, then press **It's current**. Or ask an agent to keep the
207+docs current: it finds the docs marked out of date, and its update clears
208+the mark when it's applied or accepted.
205209
206210 ## Agents and artifacts
207211
+14−4
8585
8686 <Aside type="note" title="What a reply can see today">
8787 A reply reads the conversation it is in, and looks things up while it
88−answers: code, issues, pull requests and earlier messages. It only reads
88+answers: code, issues, pull requests and their checks, earlier messages
89+and [artifacts](/guides/artifacts/#agents-and-artifacts). It only reads
8990 what everyone in the conversation can see; see
9091 [what agents can do for whom](/guides/agent-access/). In public channels
91−and conversations of more than 50 people, agents don't read code yet, so
92−ask in a DM or a private channel. Docs and checks come later.
92+and conversations of more than 50 people, agents don't read code, so ask
93+in a DM or a private channel.
9394 </Aside>
9495
9596 ## Channels
241242 | A person | It is counted as a mention in their sidebar. |
242243 | An agent that is in the channel | The agent answers in the thread. |
243244 | An agent that is not in the channel | Nothing. Invite the agent first. |
244−| `@g1t` | Nothing in Chat yet. `@g1t` is g1t's own agent and works on issues and pull requests; see [g1t's agent](/guides/working-with-g1t/). |
245+| `@g1t` | In a channel, g1t joins the first time it is mentioned, with no invite, and answers in the thread. A DM never gains a member, so to talk to g1t alone, open a DM with it. See [g1t, the orchestrator](/guides/agents/#g1t-the-orchestrator). |
245246
246247 An address such as `me@example.com` is never read as a mention.
247248
615616 your notifications still update, and everyone sees your amber dot. **Resume
616617 notifications** ends it early.
617618
619+At most three pop-ups show at once. Each stays six seconds (one with a
620+card's buttons, twelve), and stays while your pointer or keyboard is on
621+it. Nothing pops up for the conversation you have open.
622+
623+g1t never asks to show browser notifications when a page loads. After
624+your first pop-up for a DM or a mention, it offers once: **Get notified
625+when someone messages you**. If you say no, it doesn't ask again; turn
626+them on later under **Settings → Notifications**.
627+
618628 [Notifications](/guides/notifications/) are separate: they keep every item until you
619629 deal with it, whatever these settings say.
620630
+3−0
1212 https://g1t.sh/-/composer/<workspace>/
1313 ```
1414
15+Packages from Packagist still install from Packagist: add the workspace's
16+repository beside it, as [below](#install).
17+
1518 ## Make a repository a package
1619
1720 Give the repository a `composer.json` at its root with a `name`:
+345−0
1+---
2+title: Deploy g1t to Cloudflare
3+description: How g1t.sh is deployed to Cloudflare, and how to deploy the same code to an account of your own.
4+---
5+
6+g1t.sh runs on Cloudflare, and the tool that deploys it is in the
7+repository. You can deploy the same code to a Cloudflare account of your
8+own. To run g1t on one machine without Cloudflare, see
9+[Run g1t yourself](/guides/self-hosting/) instead.
10+
11+You need a Cloudflare account on the Workers Paid plan (Cloudflare
12+Artifacts, where repositories are kept, requires it), Node 22.22 or newer,
13+Rust with the `wasm32-unknown-unknown` target, and Docker to build the
14+runner's image.
15+
16+Every `wrangler.jsonc` names g1t.sh's account, domains and resource ids.
17+Before a first deploy to another account, change those to your own (see
18+[A first deploy to a new account](#a-first-deploy-to-a-new-account)).
19+
20+## The pieces
21+
22+| Piece | Where |
23+| --- | --- |
24+| The manifest: every deployable part | `deploy/stack.jsonc` |
25+| The tool | `scripts/deploy.mjs`, with its library and tests in `scripts/deploy/` |
26+| Rust Worker builds | `scripts/build-rust-worker.mjs` |
27+| The runner's images | `services/runner/base/Dockerfile`, `services/runner/Dockerfile`, `services/runner/base.json` |
28+| The workflows | `.g1t/workflows/deploy.yml`, `.g1t/workflows/runner-base.yml` |
29+
30+## The manifest
31+
32+`deploy/stack.jsonc` lists every unit: each folder with a `wrangler.jsonc`.
33+
34+| Field | What it is |
35+| --- | --- |
36+| `path` | The unit's folder |
37+| `kind` | `rust-worker`, `ts-worker`, `react-router` or `astro` |
38+| `worker` | The Worker's name. It must match its `wrangler.jsonc`. |
39+| `d1` | `{ database, migrations }`, when it has a database |
40+| `stage` | `core`, `edge` or `front` (below) |
41+| `secrets` | The Wrangler secrets it needs, by name |
42+| `setup` | One-time steps a first deploy needs that no config can say |
43+| `inputs` | Files outside its folder it is built from that no package names |
44+| `image` | A Containers image, for the runner |
45+| `self_host` | `run`, `off`, `separate` or `none`: what a [self-hosted installation](/guides/self-hosting-architecture/) does with it |
46+
47+What a unit is built from is read, never listed by hand: Rust path
48+dependencies from `cargo metadata`, workspace packages from each
49+`package.json`. A lockfile change counts for a unit only when a package
50+it uses changed. `node scripts/deploy.mjs manifest` prints the result.
51+
52+Units deploy in stages. A stage starts only when the one before it
53+succeeded, and units inside a stage deploy in parallel:
54+
55+| Stage | What |
56+| --- | --- |
57+| `migrations` | Every pending D1 migration, before any code |
58+| `core` | The services, reached through bindings |
59+| `edge` | Public endpoints other than the site: `api`, `models`, `pages`, `status` |
60+| `front` | The site, sudo and the docs |
61+
62+A unit binds only to units in its own stage or an earlier one, so new code
63+never calls a service that has not shipped. `npm run test:deploy` checks
64+this, and that every `wrangler.jsonc` has a unit whose names match it.
65+
66+## The tool
67+
68+```sh
69+node scripts/deploy.mjs plan # what would deploy, and why (read-only)
70+node scripts/deploy.mjs deploy # migrations, then every changed unit
71+node scripts/deploy.mjs deploy --only web,api # just these, if they changed
72+node scripts/deploy.mjs deploy --only web --force # just this, changed or not
73+node scripts/deploy.mjs deploy --all # everything
74+node scripts/deploy.mjs build --only events # build as a deploy would; upload nothing
75+node scripts/deploy.mjs migrate # pending migrations only
76+node scripts/deploy.mjs manifest --check # the manifest's problems
77+node scripts/deploy.mjs doctor # secrets each unit lacks
78+node scripts/deploy.mjs build-base # build and push the runner's base image (Docker)
79+node scripts/deploy.mjs image # build and push the runner's image (Docker)
80+```
81+
82+| Flag | What it does |
83+| --- | --- |
84+| `--only a,b`, `--skip a,b` | Units by short name, folder or Worker name |
85+| `--all` | Every unit, changed or not |
86+| `--force` | The selected units even if unchanged |
87+| `--concurrency N` | Units at once inside a stage, and migrations at once (default 4) |
88+| `--stage core` | One stage only |
89+| `--no-migrations` | Skip the migrations step |
90+| `--allow-dirty` | Deploy with uncommitted changes. The version records no commit, so the next plan deploys it again. |
91+| `--rebuild-image`, `--rebuild-base` | Build the runner's image, or its base, even if one exists |
92+| `--rollback` | Allow deploying a commit older than the one live |
93+| `--since REV` | Treat Workers with no recorded commit as running `REV` |
94+
95+**Only what changed deploys.** Each deploy records its commit on the
96+Worker's version (`wrangler deploy --message "g1t-deploy <sha> ..." --tag
97+g1t-<sha>`). `plan` reads the live version of each Worker, diffs from its
98+commit to `HEAD`, and deploys the units the change touches. A change only
99+to a crate's tests deploys nothing. A version deployed any other way has
100+no commit, so the unit is deployed again.
101+
102+With `CLOUDFLARE_API_TOKEN` (in CI) or `CLOUDFLARE_DEPLOY_TOKEN` (on your
103+machine) and `CLOUDFLARE_ACCOUNT_ID`, `plan` reads Cloudflare's API itself
104+and takes a few seconds. With only `wrangler login`, it asks Wrangler and
105+takes minutes. Each unit's output is kept in `$TMPDIR/g1t-deploy/<unit>.log`.
106+
107+### Migrations run while the old code is live
108+
109+Migrations apply before any code, so for a minute or more the old code
110+reads the new schema. Keep it working:
111+
112+- **Add, never change meaning.** New tables and columns with defaults are
113+ safe.
114+- **Change meaning in two deploys.** First ship code that reads both forms;
115+ then the migration that rewrites the rows.
116+- **Never drop or rename** a column or table in the same deploy that stops
117+ reading it.
118+
119+Migrations never run backwards: undoing one is a new migration.
120+
121+## The workflow
122+
123+`.g1t/workflows/deploy.yml` runs the tool on every push to `main`, and by
124+hand (**Actions → Deploy → Run workflow**) with `units`, `all` and
125+`dry_run`.
126+
127+| Job | Does |
128+| --- | --- |
129+| `check` | `manifest --check` and `npm run test:deploy` |
130+| `plan` | The plan, shown in the run's summary |
131+| `migrate` | Pending migrations; skipped when there are none |
132+| `core`, `edge`, `front` | Each stage's units, one job per build group |
133+| `smoke` | Loads the landing page, sign-in, sign-up and pricing |
134+
135+Deploys run one at a time; a second push waits. Rust units build on
136+`g1t-4core` machines, at most four to a job, with Cargo's target and
137+sccache kept in the Actions cache.
138+
139+The deploy jobs use `environment: production`, so only they can read the
140+Cloudflare token. They reach Cloudflare through the project's
141+[workflow-only domains](/guides/guardrails/), under **Settings →
142+Guardrails**:
143+
144+```text
145+api.cloudflare.com | deploy.yml | production
146+registry.cloudflare.com | deploy.yml, runner-base.yml | production
147+```
148+
149+Every deploy shows on the repository's Deployments page. A deploy run by
150+hand reports one too when `G1T_DEPLOY_TOKEN` holds a g1t token with
151+`deployments:write`.
152+
153+### The Cloudflare API token
154+
155+Make a custom token at **dash.cloudflare.com → My Profile → API Tokens**,
156+restricted to your account and zones:
157+
158+| Scope | Permission |
159+| --- | --- |
160+| Account | Workers Scripts: Edit |
161+| Account | D1: Edit |
162+| Account | Queues: Edit |
163+| Account | Workers R2 Storage: Read |
164+| Account | Account Settings: Read |
165+| Account | Containers: Edit |
166+| Zone | Workers Routes: Edit |
167+| Zone | DNS: Edit |
168+| Zone | Zone: Read |
169+
170+Store it on the repository under **Settings → Secrets and variables** as
171+the secret `CLOUDFLARE_API_TOKEN`, for workflows in the `production`
172+environment, and your account id as the variable `CLOUDFLARE_ACCOUNT_ID`.
173+A missing permission fails with `Authentication error [code: 10000]` and
174+the route it was refused on.
175+
176+## A first deploy to a new account
177+
178+What the configs refer to must exist first.
179+`node scripts/deploy.mjs manifest --json` lists, for each unit, its
180+queues, KV namespaces, R2 buckets, Vectorize indexes and dispatch
181+namespaces; its `setup` and `secrets` say the rest.
182+
183+1. Set `account_id`, routes and custom domains in each `wrangler.jsonc` to
184+ your own.
185+2. D1: `npx wrangler d1 create <database>` for each, and put its id in the
186+ unit's `wrangler.jsonc`.
187+3. KV: `npx wrangler kv namespace create <name>` for each name under
188+ `resources.kv` in the manifest, and put the ids in the configs.
189+4. Queues: `npx wrangler queues create <queue>` for each queue in the
190+ manifest, including the dead-letter queue `g1t-events-dlq`.
191+5. R2: create `g1t-screenshots`, `g1t-actions-cache` and `g1t-git-packs`,
192+ with lifecycle rules:
193+
194+ ```sh
195+ npx wrangler r2 bucket lifecycle add g1t-actions-cache expire-cache c/ --expire-days 30 --abort-multipart-days 1
196+ npx wrangler r2 bucket lifecycle add g1t-actions-cache expire-artifacts a/ --expire-days 91 --abort-multipart-days 1
197+ npx wrangler r2 bucket lifecycle add g1t-git-packs expire-packs packs/ --expire-days 7 --abort-multipart-days 1
198+ ```
199+
200+6. The runner's base image: `node scripts/deploy.mjs build-base`, then
201+ commit `services/runner/base.json`.
202+7. Everything else each unit's `setup` names: Vectorize, the dispatch
203+ namespace, DNS, Access, Email Sending and Artifacts.
204+8. Secrets: `npx wrangler secret put <NAME>` in the unit's folder.
205+ `node scripts/deploy.mjs doctor` lists what is missing.
206+9. For [Deployments](/guides/deployments/), which need the Workers for
207+ Platforms add-on and a zone for apps: `scripts/setup-deployments.sh`.
208+10. `node scripts/deploy.mjs deploy --all`. A Worker bound to a service
209+ that does not exist yet may be refused: deploy that service first with
210+ `--only`.
211+11. Register on your site to make the first account, or run
212+ `node services/identity/scripts/create-user.mjs <username>`.
213+
214+### Adding a unit
215+
216+1. Make its folder with a `wrangler.jsonc`. A Rust Worker is a member of
217+ the root `Cargo.toml`, with `node ../../scripts/build-rust-worker.mjs`
218+ as its build command and `wasm-opt = ["-O1"]`; a TypeScript one is an
219+ npm workspace.
220+2. Add it to `deploy/stack.jsonc` in the earliest stage after everything
221+ it binds to, with its secrets, setup and `self_host`.
222+3. Add a row for it to the table in
223+ [How a self-hosted g1t runs](/guides/self-hosting-architecture/#each-part).
224+4. `npm run test:deploy` and `node scripts/deploy.mjs manifest --check`
225+ say what is missing.
226+
227+## The runner's images
228+
229+`services/runner` runs every sandbox (agents, checks, the merge queue,
230+workflow jobs and deploy builds) from one Containers image in two parts:
231+
232+| Image | Built from | Rebuilt |
233+| --- | --- | --- |
234+| The base | `services/runner/base/Dockerfile`: Debian, Node, Python, Docker, Go, Rust, Java, .NET, Ruby and the Claude Code CLI | When its folder changes, weekly by `runner-base.yml`, or by hand with `build-base` |
235+| The runner | `services/runner/Dockerfile`: the base plus the `g1t-runner` binary | When the binary or the base changes |
236+
237+`services/runner/base.json` records the base that was pushed;
238+`npm run test:deploy` fails while it and the base's folder disagree. The
239+runner's image is tagged with a hash of what it is built from, so a deploy
240+builds it only when the registry does not already have it. When nothing
241+the image is built from changed, the deploy leaves running sandboxes
242+alone.
243+
244+Jobs choose larger machines with `runs-on: g1t-2core` or `g1t-4core`. Your
245+account's Containers limits must allow `standard-4`.
246+
247+Set the runner Worker's `DOCKER` variable to `off` to give workflow jobs no
248+Docker Engine.
249+
250+`CLOUDFLARE_API_TOKEN=<token> node scripts/ops/runner-errors.mjs` sorts the
251+sandboxes' errors over the last 7 days into expected ones (a deploy
252+resetting them, no free capacity, a container that stopped) and ones to
253+read.
254+
255+## Rolling back
256+
257+- **One unit, at once:** `npx wrangler rollback` in its folder. Revert the
258+ commit on `main` too, or the next push brings it back.
259+- **To a commit:** check it out and run
260+ `node scripts/deploy.mjs deploy --only <units> --rollback`. Without
261+ `--rollback` the tool refuses a unit whose live commit is newer.
262+- **The runner's image:** redeploy the older commit with
263+ `--only runner --rollback`; its image is still in the registry.
264+
265+## Other one-time setup
266+
267+### The dead-letter queue
268+
269+Every queue consumer retries a message a fixed number of times, then puts
270+it on `g1t-events-dlq`. Nothing consumes that queue: read it with
271+`npx wrangler queues info g1t-events-dlq`, fix the cause, and replay by
272+hand.
273+
274+### OIDC tokens for workflow jobs
275+
276+The API issues workflow jobs' [OIDC tokens](/guides/actions/), signed with
277+an RSA key in its secret `ACTIONS_OIDC_KEY`. Without it, jobs get no
278+tokens.
279+
280+```sh
281+openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out oidc.pem
282+cd apps/api && npx wrangler secret put ACTIONS_OIDC_KEY < ../../oidc.pem
283+rm ../../oidc.pem
284+```
285+
286+To rotate it, store the current key as `ACTIONS_OIDC_KEY_PREVIOUS`, store
287+a new one as `ACTIONS_OIDC_KEY`, and delete the previous one a day later.
288+For a key that may have leaked, skip keeping the previous one.
289+
290+### Telling the status page about deploys
291+
292+Restarts during a deploy can look like an outage to the status page's
293+checks. Set the same value as the status Worker's secret
294+`STATUS_DEPLOY_TOKEN` and as the repository's Actions secret
295+`STATUS_DEPLOY_TOKEN`, and add the status page's host to the workflow-only
296+domains. Deploys then announce their start and finish, and the status page
297+drafts no incident during them or for 3 minutes after.
298+
299+### Browser push
300+
301+`node scripts/ops/vapid-keys.mjs` prints a VAPID key pair. Put the public
302+half in `VAPID_PUBLIC_KEY` in `services/notify/wrangler.jsonc` and the
303+private half in the secret `VAPID_PRIVATE_KEY`.
304+
305+## Rate limits
306+
307+Every public surface that costs money or sends something is behind a
308+[Workers Rate Limiting](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/)
309+binding, with the limits on the [rate limits](/reference/rate-limits/)
310+page. The binding's `namespace_id` must be unique in your account. A
311+missing binding, or one that fails, lets requests through.
312+
313+## Spend guardrails
314+
315+Cloudflare has no hard spending cap. Besides each workspace's own
316+[limits](/guides/usage-and-billing/), g1t watches the platform as a whole:
317+
318+- **The hourly watch.** At a quarter past each hour, billing reads the
319+ hour before from Cloudflare's GraphQL Analytics API: Workers requests
320+ and CPU, D1 rows, Queue operations, Durable Objects, KV and Artifacts.
321+ It needs `CLOUDFLARE_BILLING_TOKEN` (or `CLOUDFLARE_USAGE_TOKEN`) with
322+ Account Analytics Read. An hour over its threshold, or over ten times
323+ the week's median hour, is emailed to `COSTS_ALERT_EMAIL`.
324+- **Thresholds** are the `PLATFORM_HOURLY_*` variables in
325+ `services/billing/wrangler.jsonc`; `0` turns one off. A breach at five
326+ times its threshold pauses the kinds of work in `AUTO_PAUSE`.
327+- **The platform pause** stops a kind of work everywhere: `compute`
328+ (sandboxes), `schedules`, `indexing` or `renders` (social cards). Staff
329+ pause and resume in sudo, under **Costs & margin**. Work already
330+ running finishes, and if the pause cannot be read, nothing is paused.
331+- **Check the watch's queries** after changing them:
332+ `CLOUDFLARE_API_TOKEN=<token> node scripts/ops/platform-usage.mjs`. It
333+ exits 1 and names any dataset that errored or answered empty.
334+
335+In Cloudflare's dashboard, which no code can set, add **Billable Usage**
336+notifications for each product g1t uses, a monthly **Budget alert**, and a
337+notification destination that reaches someone.
338+
339+## Logs
340+
341+Each Worker keeps a share of its invocations' logs, set by
342+`head_sampling_rate` in its `wrangler.jsonc`: every one for billing,
343+identity, runner, actions, deployments, status and sudo, and a tenth for
344+the rest. Metrics are not sampled. To chase a rare error on a sampled
345+Worker, raise its rate to 1 while you look.
+20−2
105105 places. A workflow deploys when any job names an `environment:`.
106106 - Secrets come from the [project on g1t](/guides/secrets-and-variables/),
107107 never the remote's.
108+- A push copied in that changes `.g1t/`, `.github/workflows/` or
109+ `.github/actions/` starts runs that wait for approval before they can
110+ use the repository's secrets and variables.
108111
109112 **End CI failover** when the remote runs its workflows again. Runs already
110113 started finish.
195198 as the `mirror_*` actions of the MCP `repository` tool. See the
196199 [API reference](/reference/api/). Reading a repository's
197200 mirroring needs read access; syncing needs push; everything else needs the
198−Admin role. Agents never move a repository to g1t or handle a remote's
199−token.
201+Admin role. Agents never move a repository to g1t, nor add, change or
202+remove a remote.
203+
204+Removing a remote makes a mirror an ordinary repository with what it has,
205+and stops pushes to a follower. It is refused during a takeover: hand it
206+back or move it to g1t first.
200207
201208 [Webhooks](/guides/webhooks/) can subscribe to:
202209
216223
217224 A takeover in progress keeps going and says why on the link: move it to
218225 g1t to keep it.
226+
227+## Not supported yet
228+
229+- Workflow results from CI failover stay on g1t; they are not reported
230+ back to the remote as checks.
231+- CI failover starts only when someone starts it.
232+- A takeover runs under the repository's own [rules](/guides/rules/) on
233+ g1t, not the remote's branch protection.
234+- A mirror doesn't show the remote's pull requests.
235+- GitLab and Bitbucket repositories link as any host over HTTPS, asked
236+ every five minutes.
+37−7
182182 Without the [g1t plan](/guides/usage-and-billing/#the-g1t-plan), public
183183 packages may hold 10 GB and private ones 500 MB per workspace; a push past
184184 either is refused, with a message saying how much is used. On the plan,
185−storage past those amounts is charged instead. See
186−[storage and pull limits](/guides/containers/#storage-and-pull-limits).
185+nothing is refused and storage past those amounts is charged instead:
186+
187+- What the workspace's packages hold is measured each day, public and
188+ private apart, each past its own free amount.
189+- A month's GB-months are those days added up, divided by 30, charged at
190+ $0.018 a GB-month as **Package storage** on the
191+ [bill](/guides/usage-and-billing/).
192+- Deleted packages and versions, kept for 30 days, do not count.
193+- Downloads and pulls cost nothing. Anonymous pulls are rate limited; see
194+ [storage and pull limits](/guides/containers/#storage-and-pull-limits).
187195
188196 ## Downloads
189197
241249 pushing a NuGet version's symbols and yanking a gem version), as are
242250 restoring them, purging them after 30 days, every change to who has access
243251 and to Manage Actions access, changing the visibility, and linking and
244−unlinking (see the [audit log's list](/guides/audit-log/)). The events
245−`package.published`, `package.version_deleted`, `package.deleted` and
246−`package.visibility_changed`, which [webhooks](/guides/webhooks/) can be
247−sent: a linked package's go to its repository's webhooks and its
248−workspace's, an unlinked package's to its workspace's webhooks.
252+unlinking (see the [audit log's list](/guides/audit-log/)).
253+
254+[Webhooks](/guides/webhooks/) can subscribe to these events. A linked
255+package's go to its repository's webhooks and its workspace's; an
256+unlinked package's go to its workspace's webhooks.
257+
258+| Event | Sent when |
259+| --- | --- |
260+| `package.published` | A version is published. `data.tags` names the tags that now point to it. |
261+| `package.version_deleted` | A version is deleted. |
262+| `package.deleted` | A package is deleted. |
263+| `package.visibility_changed` | A package is made public or private. `data.visibility` is the new one. |
264+
265+Each one's `data` has `package_id`, `workspace`, `ecosystem`, `name` and
266+`repo_id` (null for an unlinked package); a version's event also has its
267+`version` and `digest` (for a container image, the manifest's), and
268+`package.published` its `size`, except for a Composer package.
269+
270+## Not supported yet
271+
272+- PyPI packages.
273+- Installing unscoped npm packages, or other scopes, through g1t.sh, and
274+ a copy of Packagist for Composer: those still come from their public
275+ registries.
276+- A Go module proxy: Go modules are fetched with git.
277+- Workflows that run when a package is published.
278+- Packages in site-wide search.
+129−0
1+---
2+title: How a self-hosted g1t runs
3+description: What runs inside the Docker Compose installation, what stands in for each Cloudflare service, and what each part of g1t does when you run it yourself.
4+---
5+
6+[Run g1t yourself](/guides/self-hosting/) starts g1t with Docker Compose.
7+This page is for the person who keeps that installation running: what is
8+inside it, what stands in for each Cloudflare service g1t.sh uses, and
9+where the limits are.
10+
11+## The shape
12+
13+g1t is a set of Workers, one per service, each with its own SQLite
14+database. They call each other over HTTP (`POST /rpc/<method>` with a JSON
15+body). A self-hosted installation runs the same Workers, built from the
16+same source, in workerd, the open-source Workers runtime, under
17+`wrangler dev`:
18+
19+- **The site and every core service** run in one workerd process on
20+ `G1T_PORT` (8787). Their databases, key-value stores and queues are
21+ SQLite files on the `g1t-data` volume.
22+- **The API and the MCP server** run in a second workerd on `API_PORT`
23+ (8789), started once the first answers. It reaches the other services
24+ through Wrangler's local registry.
25+- **The status page** runs in a process of its own (`status.sh`), so it
26+ keeps answering when the site does not.
27+
28+Three Cloudflare services are replaced by small Workers bound in their
29+place, so no service's code changes:
30+
31+| Binding | Stands in for | Self-hosted |
32+| --- | --- | --- |
33+| `ARTIFACTS` | Cloudflare Artifacts, where g1t.sh keeps repositories | `deploy/self-host/workers/artifacts`, in front of the git store: bare repositories on the `g1t-git` volume, served with `git http-backend`. Access tokens are HMAC-signed, scoped and expire. Forks are clones with hard-linked objects. |
34+| `EMAIL` | Cloudflare Email Sending | `deploy/self-host/workers/mail`: logs each message and hands it to Mailpit, which can relay through your SMTP server |
35+| The runner, the context hub and the model proxy | Containers, Vectorize, Workers AI and AI Gateway | `deploy/self-host/workers/off`: answers that the feature is off, which every page that uses them shows |
36+
37+## What is in `deploy/self-host`
38+
39+| File | What it is |
40+| --- | --- |
41+| `docker-compose.yml` | The services: `g1t`, `status`, `gitstore`, `rustfs` (S3-compatible storage), `storage-setup` (makes the buckets once, then exits) and `mailpit`. Volumes: `g1t-data`, `g1t-git`, `g1t-objects`, `g1t-status`, `g1t-secrets`. |
42+| `Dockerfile` | Compiles the Rust services to WebAssembly and builds the site, as g1t.sh's deploys do. The image has Node, Wrangler, workerd and the built Workers. |
43+| `start.sh` | Makes the sealing keys on first start, writes the configs, applies database migrations, then starts both workerd processes and the scheduler. |
44+| `configs.mjs` | Writes each Worker's self-hosted config from its `wrangler.jsonc`: drops routes, the account and placement, binds the stand-ins above, points packages, backups, clone packs and files in pages at the S3 store, and replaces g1t.sh's addresses with yours. What runs, and what is bound to the off stand-in, comes from each part's `self_host` field in `deploy/stack.jsonc`. |
45+| `scheduler.mjs` | Runs scheduled jobs (below). |
46+| `gitstore/` | The git store. |
47+| `workers/` | The three stand-ins. |
48+| `smoke.sh` | The end-to-end check in [Check an installation](/guides/self-hosting/#check-an-installation). |
49+
50+## Each part
51+
52+| Part | Self-hosted |
53+| --- | --- |
54+| `apps/web` | Runs: the site, on `G1T_PORT` |
55+| `apps/api` | Runs in the second workerd, on `API_PORT`. `API_URL` is its OAuth issuer and MCP is at `/mcp` on it. Actions artifacts need the runner, which is off. |
56+| `apps/status` | Runs in a process of its own; see [the status page](/guides/self-hosting/#the-status-page) |
57+| `apps/sudo` | Not run. It is g1t.sh's staff console, behind Cloudflare Access. |
58+| `apps/docs` | Not run: docs.g1t.sh serves these pages |
59+| `services/identity` | Runs; its email goes to Mailpit |
60+| `services/repos` | Runs, against the git store. Nightly backups are queued but cut by the runner, which is off, so none are made yet. Clone packs are kept in the `g1t-git-packs` bucket. |
61+| `services/work` | Runs |
62+| `services/events` | Runs: the event bus, on local queues |
63+| `services/projects` | Runs |
64+| `services/search` | Runs: site search is SQLite full-text search |
65+| `services/chat` | Runs, with its Durable Objects; custom emoji are kept with avatars |
66+| `services/docs` | Runs: pages and [artifacts](/guides/artifacts/), with their live rooms. Files people add are kept in the `g1t-docs-files` bucket. Search matches words, not meaning, because there is no embedding model. |
67+| `services/notify` | Runs. Notifications are live in open tabs; browser push needs a VAPID key pair, which an installation does not make. |
68+| `services/agents` | Runs, but replies need the model proxy, which is off, so an agent answers with a short apology |
69+| `services/billing` | Runs with nothing charged and no usage limit |
70+| `services/integrations` | Runs |
71+| `services/webhooks` | Runs, retries included |
72+| `services/actions` | Runs. Jobs need the runner, which is off. |
73+| `services/packages` | Runs, with files in the `g1t-packages` bucket and no request size limit |
74+| `services/security` | Runs, with its sweeps on schedule |
75+| `services/deployments` | Runs with no Cloudflare token, so nothing deploys; its pages and settings still show |
76+| `services/runner` | Off: agents, checks run by g1t, merge queue testing and workflow jobs |
77+| `services/context` | Off: the context hub |
78+| `services/models` | Off: g1t's hosted models |
79+| `services/pages` | Not run: there is no `g1t.page` |
80+| `services/og` | Not run: pages have no social cards |
81+
82+## Scheduled jobs
83+
84+workerd runs a Worker's scheduled handler only when asked. `scheduler.mjs`
85+asks once a minute, inside the `g1t` container, through Wrangler's local
86+API, for each due schedule in the Workers' own configs: repos, events,
87+identity, security, webhooks, packages and docs. A job still running from
88+the minute before is not started again, and one is given up on after ten
89+minutes.
90+
91+Not run: Actions schedules (`on: schedule`, which would need the runner),
92+billing and deployments.
93+
94+`node deploy/self-host/scheduler.mjs --once /data/generated/schedules.json`
95+runs every job once and exits non-zero if one failed.
96+
97+## Storage
98+
99+Every bucket is on the bundled RustFS, or on any S3-compatible store you
100+point `S3_ENDPOINT` at (MinIO, Ceph, Garage or AWS S3). `storage-setup`
101+makes them on the bundled store; on another store, make them yourself.
102+
103+| Bucket | Holds | Setting |
104+| --- | --- | --- |
105+| `g1t-packages` | Container image layers and other package files | `S3_BUCKET` |
106+| `g1t-git-packs` | Packs for fresh clones, a cache. Give it a rule that deletes objects after 7 days and aborts multipart uploads after a day. | `PACK_S3_BUCKET` |
107+| `g1t-backups` | Nightly repository backups, once the runner cuts them | `BACKUP_S3_BUCKET` |
108+| `g1t-docs-files` | Images and files added to pages and artifacts | `DOCS_S3_BUCKET` |
109+
110+Requests to the store are signed with AWS Signature Version 4, path style.
111+
112+## Limits
113+
114+- **Use it on `localhost` or a private network you trust.** `wrangler dev`
115+ is a development server: it answers its own development endpoints
116+ (`/cdn-cgi/...`) on the same port as the site.
117+- **One machine.** Every database is a SQLite file with one writer. It
118+ suits a team, not a large organisation.
119+- **HTTPS anywhere but `localhost`.** Sign-in cookies are `Secure`; put a
120+ proxy with a certificate in front and set `PUBLIC_URL` to its
121+ `https://` address.
122+- **If the API says a binding is `[not connected]`**, restart the
123+ container: the API finds the other services through Wrangler's local
124+ registry.
125+- **Building takes minutes and several GB**, because every Rust service is
126+ compiled from source. A change that does not compile breaks the image,
127+ so build from a released commit.
128+- **Some links still leave your installation**: the docs links go to
129+ docs.g1t.sh, and the Status links to status.g1t.sh.
+6−3
3333 | Billing | Off. Nothing is charged, and no usage limit stops work. |
3434 | Site analytics | Off. Only g1t.sh sends page analytics (to HeyCatch, as its [privacy policy](https://g1t.sh/policies/privacy#how-the-site-is-used) describes); your installation sends none. |
3535 | Git over SSH and the `g1t` CLI | Not available yet |
36−| Scheduled jobs | Run on their schedules inside the g1t container: webhook retries, purging deleted repositories, the packages sweep, security sweeps, audit log retention and access request summaries. Actions schedules (`on: schedule`) are not run. |
36+| Scheduled jobs | Run on their schedules inside the g1t container: webhook retries, purging deleted repositories, the packages sweep, security sweeps, audit log retention, access request summaries and emptying artifacts left in the trash for 30 days. Actions schedules (`on: schedule`) are not run. |
3737
3838 What hosted g1t cannot do yet either is on
39−[What g1t can't do yet](/about/limitations/).
39+[What g1t can't do yet](/about/limitations/). What runs inside the
40+installation, and what stands in for each part of g1t.sh, is in
41+[How a self-hosted g1t runs](/guides/self-hosting-architecture/).
4042
4143 ## Before you start
4244
164166 | `S3_ENDPOINT`, `S3_BUCKET`, `S3_REGION`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY` | the bundled RustFS, bucket `g1t-packages` | Where packages' files are kept: any S3-compatible store. Change the two keys before first start; RustFS is made with them. |
165167 | `S3_PUBLIC_ENDPOINT` | (none) | The store's address as clients reach it. When set, large layers are downloaded from it directly with a signed URL. |
166168 | `PACK_S3_BUCKET` | `g1t-git-packs` | The bucket on the same store that packs for fresh clones are kept in, so the next clone of the same commit is not built again. The bundled store deletes packs after 7 days, and uploads left unfinished after a day; on another store, give the bucket a lifecycle rule that does the same. |
169+| `DOCS_S3_BUCKET` | `g1t-docs-files` | The bucket on the same store that images and files added to pages and [artifacts](/guides/artifacts/) are kept in. |
167170 | `RUSTFS_IMAGE` | `rustfs/rustfs:1.0.1` | The image the bundled object store runs: [RustFS](https://rustfs.com), an S3-compatible server. |
168171 | `AWS_CLI_IMAGE` | `amazon/aws-cli:2.37.10` | The image `storage-setup` makes the buckets and the packs' lifecycle rule with. |
169172 | `BACKUP_S3_BUCKET` | `g1t-backups` | The bucket on the same store that nightly repository backups (a `git bundle` of each repository whose branches or tags changed) are kept in. The bundles are cut by g1t's runner, which this installation does not run yet, so the bucket stays empty for now: copy the volumes, as below. |
245248 | --- | --- |
246249 | `g1t_g1t-data` | Accounts, workspaces, issues and every other record, as SQLite files; the keys that seal stored secrets (`keys.env`) |
247250 | `g1t_g1t-git` | Your repositories, one bare git repository each |
248−| `g1t_g1t-objects` | The bundled object store (RustFS): container images' layers and other package files in `g1t-packages`, the `g1t-backups` bucket and the clone packs in `g1t-git-packs` |
251+| `g1t_g1t-objects` | The bundled object store (RustFS): container images' layers and other package files in `g1t-packages`, the `g1t-backups` bucket, the clone packs in `g1t-git-packs`, and files added to pages and artifacts in `g1t-docs-files` |
249252 | `g1t_g1t-secrets` | The key the site and the git store share |
250253
251254 To back up, stop g1t and copy the volumes:
+1−2
767767 | [`accept_repository_invitation`](/reference/api/access/accept-repo-invitation/) | Accept one; its role is yours at once. | `id` | `account:write` |
768768 | [`decline_repository_invitation`](/reference/api/access/decline-repo-invitation/) | Decline one. | `id` | `account:write` |
769769
770−
771770 ## `artifact`
772771
773772 A workspace's artifacts: its docs, and later its slides, designs and
792791 | [`query_data`](/reference/api/artifacts/query-workspace-dataset/) | Run a dataset `query` as you, over what you can read. Answers that dashboards are not here yet until they ship. | `workspace`, `query` | `artifacts:read` |
793792 | [`create`](/reference/api/artifacts/create-workspace-artifact/) | Make one from `markdown` or a `template_id`, in a `space`, under a `parent_id`, or in your Private. `kind` is `doc`; the others are not here yet. | `workspace` | `artifacts:write` |
794793 | [`update`](/reference/api/artifacts/update-workspace-artifact/) | Change its `title` or `icon`, or move it to a `space` (`private` for your Private) or under a `parent_id`. | `workspace`, `artifact_id` | `artifacts:write` |
795−| [`edit`](/reference/api/artifacts/edit-workspace-artifact/) | Change its content: `markdown` with a `target` (`append`, `document`, a `section` by `heading`, or `blocks`). Made with the edit role; a suggestion with the comment role or `suggest_only`. | `workspace`, `artifact_id` | `artifacts:write` |
794+| [`edit`](/reference/api/artifacts/edit-workspace-artifact/) | Change its content: `markdown` with a `target` (`append`, `document`, a `section` by `heading`, or `blocks`). Made with the edit role; a suggestion with the comment role or `suggest_only`. `note` says why; `marks_current` clears the doc's possibly out of date mark when the change is made or accepted. | `workspace`, `artifact_id` | `artifacts:write` |
796795 | [`trash`](/reference/api/artifacts/trash-workspace-artifact/) | Move it, and what is under it, to the trash; deleted for good after 30 days. | `workspace`, `artifact_id` | `artifacts:write` |
797796 | [`restore`](/reference/api/artifacts/restore-workspace-artifact/) | Bring it back from the trash. | `workspace`, `artifact_id` | `artifacts:write` |
798797 | [`restore_version`](/reference/api/artifacts/restore-workspace-artifact-version/) | Make an earlier version its content again, as a new version. | `workspace`, `artifact_id`, `version_id` | `artifacts:write` |
+1−1
6464 /**
6565 * The page-speed budget the status page holds the site to: the slower of a
6666 * public project page and Explore, to the first byte of the answer, from a
67− * Cloudflare data centre. docs/PERFORMANCE.md has the targets.
67+ * Cloudflare data centre. CONTRIBUTING.md, "Speed", has the site's targets.
6868 */
6969 export const SPEED_BUDGET_MS = 800;
7070
+2−2
211211 context, prices, typical run and when its provider last listed it, each
212212 with **Retire** or **Restore**. **Checks**: the latest checks of each
213213 provider. Every change names the staff member and why in the audit log
214− (account `models`). See docs/BILLING_OPERATIONS.md, "The model
215− catalogue".
214+ (account `models`). The catalogue itself is billing's
215+ (`services/billing/src/catalogue.rs`).
216216 - **Stripe**: whether billing's key is in test or live mode (or off), the
217217 webhook Stripe calls (URL, endpoint id, events, who registered it and
218218 when), and the events Stripe sent lately with what billing did with
+4−4
507507
508508
509509 /**
510− * The platform pause and the hourly usage watch (billing's platform.rs,
511− * docs/SPEND-GUARDRAILS.md): four levels staff can pause across g1t, what
512− * Cloudflare counted in the last hour against each threshold, and the
513− * last day's breaches.
510+ * The platform pause and the hourly usage watch (billing's platform.rs;
511+ * docs.g1t.sh/guides/deploy-to-cloudflare/#spend-guardrails): four levels
512+ * staff can pause across g1t, what Cloudflare counted in the last hour
513+ * against each threshold, and the last day's breaches.
514514 */
515515 function PlatformSection({
516516 guard,
+3−3
1515 export const DEPARTMENTS = ["Engineering", "QA", "Operations", "Docs", "Product", "Customer Support", "Sales"];
1616
1717 /**
18− * An agent's role (docs/WORKSPACE.md, "Roles, not tasks"): its title, the
19− * team it is on (or a department, when it is on none), and what it is
20− * responsible for, as a list to add to, edit and reorder.
18+ * An agent's role: its title, the team it is on (or a department, when it
19+ * is on none), and what it is responsible for, as a list to add to, edit
20+ * and reorder.
2121 */
2222 export function RoleFields({
2323 title,
+1−1
4747 import { sessionChip } from "../../lib/session-card";
4848 import { codeAccessPath } from "../../lib/workspace-nav";
4949
50−// A card g1t or an agent posts in chat (docs/WORKSPACE.md, "Cards"): what
50+// A card g1t or an agent posts in chat: what
5151 // it is about, its state, a preview, a few facts, and what people can do
5252 // right here. Pressing an action goes to the site (routes/workspace/chat/
5353 // api.ts, `card_action`), then to chat, then to the service that owns the
+1−1
8484 return new Date(at).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", timeZone: zone });
8585 }
8686
87−/** Whether the viewer uses Code in this workspace (docs/WORKSPACE.md, "Members without Code"). */
87+/** Whether the viewer uses Code in this workspace. */
8888 export function useCodeAccess(slug: string): boolean {
8989 const root = useRouteLoaderData("root") as { user?: { workspaces?: { slug: string; code_access?: boolean }[] } | null } | undefined;
9090 return hasCodeAccess(root?.user?.workspaces?.find((m) => m.slug === slug) ?? null);
+2−1
99 import { SelectField } from "../ui/select";
1010 import { ORCHESTRATOR, type WritableSpace, type WriteUpAgent, type WriteUpWhere, defaultWhere, writableSpaces, writeUpMessage } from "../../lib/write-up";
1111
12−// "Write this up as an artifact" (docs/ARTIFACTS_MODE.md section 4.4):
12+// "Write this up as an artifact" (docs.g1t.sh/guides/artifacts/, "Write a
13+// thread up"):
1314 // where it goes, a title if you have one, and which agent writes it. The
1415 // kind is a doc for now. Sending posts the ask in the thread, as you,
1516 // where everyone sees it; the agent answers it as it answers any mention,
+1−1
243243 }
244244
245245 /**
246− * The dock down the left (docs/WORKSPACE.md, "Shell"): g1t's mark, which
246+ * The dock down the left: g1t's mark, which
247247 * leads to Today; the built-in apps (Today, Chat, Notifications, Agents,
248248 * Code and Artifacts) with their names; the apps you pinned, as icons;
249249 * the Apps launcher; and at its foot People, Workspace and your account.
+1−2
11 /**
22 * Docs and code: citing code in a doc (the Cite code dialog), and showing
3− * a project's docs folder in Artifacts. Plan: docs/WORKSPACE.md, "Agents
4− * and docs" and "Docs and repository docs".
3+ * a project's docs folder in Artifacts.
54 */
65 import { DOC_CITATION_KIND_LABELS, type DocCitationKind, type DocRepoSpace } from "@g1t/contracts";
76 import { FileCode2, FolderGit2 } from "lucide-react";
+2−2
11 /**
22 * Each kind of artifact as the site shows it: its icon and colour, whether
33 * it can be made yet, and its page body. One line per kind, so each kind's
4− * phase adds its own (docs/ARTIFACTS_MODE.md section 8: slides, design and
5− * dashboards are "Coming soon" until theirs ships). Bodies are lazy, so
4+ * phase adds its own (slides, design and dashboards are "Coming soon"
5+ * until theirs ships). Bodies are lazy, so
66 * Home and the sidebar carry no editor code.
77 */
88 import { FOLIO_KIND_LABELS, type DocRole, type Folio, type FolioKind, type FolioPage, type FolioPreview } from "@g1t/contracts";
+1−1
11 /**
2− * Artifacts as lists show them (docs/ARTIFACTS_MODE.md section 6.2): rows
2+ * Artifacts as lists show them: rows
33 * grouped by the day they were last edited, in the viewer's time zone, or
44 * cards with a picture drawn from each one's preview. Each has its kind,
55 * who can see it, its space, when it was edited and by whom, and its ⋯
+1−1
11 /**
2− * Share an artifact (docs/ARTIFACTS_MODE.md section 6.4): invite people,
2+ * Share an artifact (docs.g1t.sh/guides/artifacts/, "Sharing"): invite people,
33 * agents and teams with a role, see everyone who has access and where it
44 * comes from, choose whether it follows its space or parent or only
55 * people invited, open it to the workspace or to anyone in it with the
+2−2
11 /**
2− * The header every artifact's page shares, whatever its kind
3− * (docs/ARTIFACTS_MODE.md section 6.5): where it is (a space or Private,
2+ * The header every artifact's page shares, whatever its kind: where it
3+ * is (a space or Private,
44 * then the docs it sits under), who is here, "Offline, changes will
55 * sync", and Share, comments, history, favorite and the ⋯ menu. A kind's
66 * own actions go in `actions`.
+2−2
11 /**
2− * Artifacts mode's sidebar (beside the rail; docs/ARTIFACTS_MODE.md
3− * section 6.3): search, Home, New and Templates; Favorites; the spaces
2+ * Artifacts mode's sidebar (beside the rail; docs.g1t.sh/guides/artifacts/,
3+ * "The sidebar"): search, Home, New and Templates; Favorites; the spaces
44 * shown (joined open spaces, team spaces, members-only spaces) each with
55 * its tree; Private, everything of yours in no space; Shared, the tops of
66 * what others shared with you; then what's possibly out of date,
+5−5
11 /**
2− * Chat's cards for artifact links (docs/ARTIFACTS_MODE.md section 4.3 rule
3− * 3): each viewer asks the site for their own, so someone who can open the
4− * artifact sees its kind, title, space and last edit, and anyone else sees
5− * only "An artifact you don't have access to", with no title. Looking is
6− * not opening: a card never makes a link-shared artifact readable.
2+ * Chat's cards for artifact links (docs.g1t.sh/guides/artifacts/, "Links
3+ * in chat"): each viewer asks the site for their own, so someone who can
4+ * open the artifact sees its kind, title, space and last edit, and anyone
5+ * else sees only "An artifact you don't have access to", with no title.
6+ * Looking is not opening: a card never makes a link-shared artifact readable.
77 */
88 import type { FolioKind, Result } from "@g1t/contracts";
99 import { Lock } from "lucide-react";
+5−5
1010 import { currentSink, dismiss, settle, useWaitingCards } from "../../lib/notify-client";
1111 import { cardActionRequest, notificationActions } from "../../lib/notify-store";
1212
13−// A chat card's actions on a notification about it (docs/WORKSPACE.md,
14−// "Cards"): a session at its cap (Approve more with the amount inline,
15−// Stop, Open), a draft issue (File issue, Discard). Pressing one sends the
16−// same `card_action` as the card in the conversation; the card there
17−// changes for everyone, and this notification is put away.
13+// A chat card's actions on a notification about it: a session at its cap
14+// (Approve more with the amount inline, Stop, Open), a draft issue (File
15+// issue, Discard). Pressing one sends the same `card_action` as the card
16+// in the conversation; the card there changes for everyone, and this
17+// notification is put away.
1818
1919 const BASE =
2020 "inline-flex h-7 shrink-0 items-center justify-center gap-1 rounded-md px-2.5 text-xs font-medium transition-colors outline-none focus-visible:ring-2 focus-visible:ring-accent/50 disabled:pointer-events-none disabled:opacity-50 max-sm:h-9 max-sm:px-3";
+2−3
33 import { Mark } from "./logo";
44
55 /**
6− * Whether an agent is `@g1t`, the orchestrator every workspace has
7− * (docs/WORKSPACE.md, "g1t, the orchestrator"): built in, first in the
8− * agents service's list. Its handle is never another agent's.
6+ * Whether an agent is `@g1t`, the orchestrator every workspace has: built
7+ * in, first in the agents service's list. Its handle is never another agent's.
98 */
109 export function isOrchestrator(agent: Pick<WorkspaceAgent, "handle"> & { builtin?: boolean | null }): boolean {
1110 return agent.builtin === true || agent.handle === "g1t";
+1−1
17591759 }
17601760
17611761 /**
1762− * The app (docs/WORKSPACE.md, "Shell"): three surfaces that never blur
1762+ * The app: three surfaces that never blur
17631763 * together. The dock, a floating bar of apps down the left; the mode's
17641764 * sidebar, flat on the background beside it, which folds away with Ctrl B
17651765 * and is a drawer below 1024px; and the page, a rounded panel inset from
+1−1
11 /**
2− * Cards people can act on in chat (docs/WORKSPACE.md, "Cards"): how a
2+ * Cards people can act on in chat: how a
33 * card's state reads, which of its actions are links and which run, and
44 * the money and text people type into them. Pure, so it is tested on its
55 * own; components/chat/card.tsx draws them.
+1−1
11 /**
22 * Artifacts mode's pure helpers (code says "folio", people see
3− * "artifact"; docs/ARTIFACTS_MODE.md): sidebar trees, the home list's
3+ * "artifact"): sidebar trees, the home list's
44 * days, cursor colours, covers, roles, how search snippets mark their
55 * matches, and projects' docs folders. No Workers or DOM imports, so it is
66 * tested under Node.
+2−1
11 /**
22 * The front door's rate limits (workers/app.ts), per request before it is
33 * answered. The bindings and their limits are in `RATE_LIMITS`
4− * (packages/contracts/src/rate-limits.ts); docs/RATE-LIMITS.md says why.
4+ * (packages/contracts/src/rate-limits.ts); CONTRIBUTING.md, "Rate limits",
5+ * says how they are kept.
56 *
67 * - Git over HTTPS: without credentials, by address; with them, by a hash
78 * of the credential, much higher. A clone is about three requests.
+1−1
4040 const root = new URL("../../../../", import.meta.url);
4141 const SAMPLES: [string, string][] = [
4242 ["README.md", readFileSync(new URL("README.md", root), "utf8")],
43− ["docs/PERFORMANCE.md", readFileSync(new URL("docs/PERFORMANCE.md", root), "utf8")],
43+ ["apps/docs/src/content/docs/guides/deploy-to-cloudflare.md", readFileSync(new URL("apps/docs/src/content/docs/guides/deploy-to-cloudflare.md", root), "utf8")],
4444 ["CONTRIBUTING.md", readFileSync(new URL("CONTRIBUTING.md", root), "utf8")],
4545 [
4646 "edge cases",
+3−3
4343 // ── The desktop bridge ───────────────────────────────────────────────────
4444
4545 /**
46− * What the desktop app (an Electron shell loading this web app; see
47− * docs/WORKSPACE.md, "Desktop app") exposes from its preload script with
46+ * What the desktop app (an Electron shell loading this web app) exposes
47+ * from its preload script with
4848 * `contextBridge.exposeInMainWorld("g1tDesktop", …)`. When it is there,
4949 * notifications go to it instead of the browser:
5050 *
233233 set({ settled: new Set(state.settled).add(id), toasts: dismissToast(state.toasts, id) });
234234 }
235235
236−/** The chat cards waiting on the person (docs/WORKSPACE.md, "Cards"), newest first, for the panel. */
236+/** The chat cards waiting on the person, newest first, for the panel. */
237237 export function useWaitingCards(workspace?: string | null): FeedNotification[] {
238238 const s = useNotifyState();
239239 return waitingCards(s.recent, s.settled, Date.now(), workspace);
+1−1
9696
9797 // ── Cards ─────────────────────────────────────────────────────────────────
9898
99−/** A card's actions on its notification: what the toast and the panel offer (docs/WORKSPACE.md, "Cards"). */
99+/** A card's actions on its notification: what the toast and the panel offer. */
100100 export function notificationActions(notification: FeedNotification): CardAction[] {
101101 const card = notification.card;
102102 if (!card || !notification.workspace || !card.channel_id || !card.message_id) return [];
+1−1
22 * The pure parts of request timing and D1 read consistency for the site:
33 * the `g1t_d1` cookie, which session each service call asks for, which
44 * calls may write, and the `Server-Timing` header. perf.server.ts holds
5− * the per-request state; docs/PERFORMANCE.md explains the whole.
5+ * the per-request state; CONTRIBUTING.md, "Speed", says how to use it.
66 */
77
88 /** The cookie that carries D1 bookmarks between a person's requests. */
+3−3
7575 // from wherever it was going (lib/confirm-gate.ts).
7676 const gated = confirmGate(pathname, search, viewer);
7777 if (gated) throw redirect(gated);
78− // A member without Code access in a workspace (docs/WORKSPACE.md,
79− // "Members without Code"): their Home in place of Mission control, and
80− // the page that says to ask an owner in place of anything of Code's.
78+ // A member without Code access in a workspace: their Home in place of
79+ // Mission control, and the page that says to ask an owner in place of
80+ // anything of Code's.
8181 // The services enforce it too; this keeps the site from offering it.
8282 const noCode = (viewer?.workspaces ?? []).filter((m) => !hasCodeAccess(m)).map((m) => m.slug.toLowerCase());
8383 if (request.method === "GET" && noCode.length > 0) {
+1−1
113113 }
114114
115115 /**
116− * The dock's modes (docs/WORKSPACE.md, "Shell"). Today is the front page;
116+ * The dock's modes. Today is the front page;
117117 * Chat, Agents, Code and Artifacts are where work happens; Notifications
118118 * spans them; People is who belongs; Workspace is the workspace itself:
119119 * its money, policies and settings; Apps is everything installed that you
+7−7
11 /**
2− * "Write this up as an artifact" from chat (docs/ARTIFACTS_MODE.md section
3− * 4.4): where it goes (a space, Private, or shared with the conversation),
4− * the agents that can write it, and the message that asks one to. Nothing
5− * is written behind anyone's back: the person posts the ask in the thread,
6− * as themselves, and the agent answers it the usual way (a session if it
7− * needs one, then `create_artifact`). The kind is a doc until slides and
8− * the other kinds ship. Pure, so it is tested on its own;
2+ * "Write this up as an artifact" from chat (docs.g1t.sh/guides/artifacts/,
3+ * "Write a thread up"): where it goes (a space, Private, or shared with
4+ * the conversation), the agents that can write it, and the message that
5+ * asks one to. Nothing is written behind anyone's back: the person posts
6+ * the ask in the thread, as themselves, and the agent answers it the usual
7+ * way (a session if it needs one, then `create_artifact`). The kind is a
8+ * doc until slides and the other kinds ship. Pure, so it is tested on its own;
99 * components/chat/write-up.tsx draws the dialog.
1010 */
1111 import type { DocRole, MemberProfile } from "@g1t/contracts";
+1−1
383383 <meta name="apple-mobile-web-app-capable" content="yes" />
384384 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
385385 {/* The stylesheet before everything React Router preloads, so a slow
386− connection paints sooner (docs/research/css-shipping.md). */}
386+ connection paints sooner. */}
387387 <link rel="stylesheet" href={appCss} precedence="default" />
388388 {root?.analyticsConsent && <meta name="g1t-analytics" content="consent" />}
389389 <Meta />
+3−3
141141 route("-/settings/chat", "routes/workspace/chat-settings.tsx"),
142142 route("-/repositories", "routes/workspace/repositories.tsx"),
143143 // Agents mode: the overview (budget, sessions, roster, spend) first, then
144− // each of the workspace's own agents and its sessions (docs/WORKSPACE.md).
144+ // each of the workspace's own agents and its sessions.
145145 // `new` is no agent's handle.
146146 route("-/agents", "routes/workspace/agents/layout.tsx", [
147147 index("routes/workspace/agents.tsx"),
168168 route("dm/:id", "routes/workspace/chat/channel.tsx", { id: "routes/workspace/chat/dm" }),
169169 route(":channel", "routes/workspace/chat/channel.tsx"),
170170 ]),
171− // Artifacts mode (docs/ARTIFACTS_MODE.md; code says "folio"): what its
171+ // Artifacts mode (code says "folio"): what its
172172 // pages call as they run (an artifact's live socket, JSON, comments,
173173 // uploads, export), then Home, making one, templates, the trash, the
174174 // spaces, and each artifact by its address. Addresses are flat and end
198198 route("-/today", "routes/workspace/home.tsx"),
199199 route("-/home", "routes/workspace/moved.ts", { id: "routes/workspace/moved-home" }),
200200 route("-/apps", "routes/workspace/apps.tsx"),
201− // What Code's pages say to a member without Code (docs/WORKSPACE.md, "Members without Code").
201+ // What Code's pages say to a member without Code.
202202 route("-/code-access", "routes/workspace/code-access.tsx"),
203203 route("-/memory", "routes/workspace/memory.tsx"),
204204 route("-/context", "routes/workspace/context.tsx"),
+1−1
101101 overage: "Everything is metered from the first unit at what it costs g1t plus 20%. Unused included usage does not roll over.",
102102 };
103103
104−/** How each part of a workspace is charged: the plan's Pricing table (docs/WORKSPACE.md). */
104+/** How each part of a workspace is charged. */
105105 const WORKSPACE_CHARGES: { what: string; how: string; soon?: boolean }[] = [
106106 {
107107 what: "People chatting",
+1−2
1212
1313 /**
1414 * What a member without Code access sees in place of a repository, an
15− * issue, a pull request or a project list (docs/WORKSPACE.md, "Members
16− * without Code"): what it was, and who to ask.
15+ * issue, a pull request or a project list: what it was, and who to ask.
1716 */
1817 export async function loader({ params, context, request }: Route.LoaderArgs) {
1918 const viewer = requireUser(context, request);
+1−1
6363 };
6464
6565 /**
66− * Artifacts' home (docs/ARTIFACTS_MODE.md section 6.2): search and
66+ * Artifacts' home (docs.g1t.sh/guides/artifacts/, "Home"): search and
6767 * filters, All / Yours / Shared with you, tiles to make something new,
6868 * and everything you can open, grouped by the day it was last edited, or
6969 * as cards.
+1−1
1111 import { knownTimeZone } from "../../../lib/time-zone";
1212
1313 /**
14− * Artifacts mode (docs/ARTIFACTS_MODE.md; code says "folio"): what its
14+ * Artifacts mode (code says "folio"): what its
1515 * sidebar shows (the shell draws it from this data: favorites, spaces and
1616 * their trees, Private, Shared, projects' docs), who can be mentioned or
1717 * shared with, and the viewer's time zone for the home list's days. Each
+3−3
115115 * Public pages as someone signed out sees them: the same for every such
116116 * visitor, so kept in this data centre's cache. Reserved first segments
117117 * (settings, sign-in, invitations and the like) and workspace pages (`-`)
118− * are never kept; docs/PERFORMANCE.md lists the rules. A repository's kept
119− * page is served only while repos says the repository is still public: one
120− * made private or deleted is never served from any data centre's copy.
118+ * are never kept. A repository's kept page is served only while repos
119+ * says the repository is still public: one made private or deleted is
120+ * never served from any data centre's copy.
121121 */
122122 const PUBLIC_TOP = /^\/(?:|_root\.data|pricing|explore|security|support|policies(?:\/[a-z-]+)?)(?:\.data)?$/;
123123 const PUBLIC_PROJECT =
+1−1
66 // AsyncLocalStorage, for per-request timings and D1 bookmarks
77 // (app/lib/perf.server.ts).
88 "compatibility_flags": ["nodejs_als"],
9− // Where it runs: docs/PERFORMANCE.md. Off runs it in the data centre
9+ // Where it runs (CONTRIBUTING.md, "Speed"). Off runs it in the data centre
1010 // nearest the visitor; scripts/perf/placement-probe.mjs measures the
1111 // alternatives and `apply` changes every Worker's at once.
1212 "placement": { "mode": "off" },
+2−2
11 #!/usr/bin/env node
22 // Runs g1t's pull request reviewer over ReviewBench and scores it with the
3−// benchmark's own judge. docs/research/reviewbench.md explains the design.
3+// benchmark's own judge.
44 //
55 // node bench/reviewbench/run.mjs setup clone ReviewBench (pinned) and install its judge
66 // node bench/reviewbench/run.mjs build build the agent image from the runner base image
114114 * growing context every turn, mostly from cache: turns and context grow
115115 * with the size of the change. Calibrate against real review runs (the
116116 * billing ledger records each run's cost) before trusting the absolute
117− * numbers; see docs/research/reviewbench.md.
117+ * numbers.
118118 */
119119 function estimateOne(p, model) {
120120 const [, output, cacheRead, cacheWrite] = PRICES[model] ?? PRICES[DEFAULT_MODEL];
+1−1
11 //! g1t's own workflows (`.g1t/workflows/*.yml`), read by the same parser
22 //! and expressions the actions service runs them with: each reads, nothing
33 //! in it is unsupported, and the deploy workflow's jobs start, wait and
4−//! stop as docs/DEPLOYING.md says.
4+//! stop as docs.g1t.sh/guides/deploy-to-cloudflare/ says.
55
66 use std::path::PathBuf;
77
+1−1
11 //! Repository backups: a nightly `git bundle` of every repository whose
2−//! refs changed, kept outside the git store (docs/ARTIFACTS.md, R11).
2+//! refs changed, kept outside the git store.
33 //!
44 //! The repos service decides what is due and keeps the bundles and their
55 //! manifests (services/repos/src/backups.rs). It cannot run git, so the
+2−1
37333733 pub by: String,
37343734 }
37353735
3736−// ---- Platform pauses and the usage watcher (docs/SPEND-GUARDRAILS.md) ----
3736+// ---- Platform pauses and the usage watcher ----
3737+// docs.g1t.sh/guides/deploy-to-cloudflare/#spend-guardrails
37373738
37383739 /// A g1t-wide pause, set by staff in sudo or by billing's hourly usage
37393740 /// watcher on a severe breach. Each level is independent.
+1−1
480480 "restore_package_version",
481481 // Sharing an artifact and deleting one for good are for people: an
482482 // agent shares only through the agents service, with the people
483− // already in its conversation (docs/ARTIFACTS_MODE.md, section 4.3).
483+ // already in its conversation.
484484 "set_workspace_artifact_access",
485485 "purge_workspace_artifact",
486486 ];
+3−4
1−//! Datasets: the safe query layer behind dashboards (Artifacts mode,
2−//! docs/ARTIFACTS_MODE.md section 3.4). Mirrors
3−//! `packages/contracts/src/datasets.ts`; the tests here keep the catalog the
4−//! same and run both validators over `datasets.fixtures.json`.
1+//! Datasets: the safe query layer behind dashboards (Artifacts mode).
2+//! Mirrors `packages/contracts/src/datasets.ts`; the tests here keep the
3+//! catalog the same and run both validators over `datasets.fixtures.json`.
54 //!
65 //! Not SQL: a query names a dataset from a declared catalog, one measure,
76 //! at most one dimension, an interval, filters on declared fields and a
+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

+0−0

Binary or large file; its contents are not shown.

This change is too large to show in full.