Skip to content
1,984 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Workspaces own repositories1# g1t plan
2
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas3g1t is where people and agents ship software together: a git platform built on Cloudflare Workers and Artifacts for
Workspaces own repositories4the "Build the Next-Gen Git Platform on Cloudflare" competition.
5
6- Submission closes **October 14, 2026, 11:59 PM PDT**: a 5–10 minute demo
7 video, this repository (MIT) and run instructions.
8- Judging: 50% originality and quality of the prototype for agent-oriented
9 collaboration; 25% multi-agent concurrency, coordination, context
10 preservation, review and conflict handling; 25% ease of use.
11
Agents as a team: lifecycle, merge queue, billing and a new shell12## The point
13
The plan says what g1t is for without measuring it against other products14**g1t is where a team of agents ships code, with the people they work for.**
Agents as a team: lifecycle, merge queue, billing and a new shell15
The plan says what g1t is for without measuring it against other products16Hosting git is table stakes, and g1t does it the familiar way: issues,
Agents as a team: lifecycle, merge queue, billing and a new shell17branches, pull requests, review, protected branches, people working by hand.
18None of that is the selling point. The selling point is the layer above it,
19which no forge has: **you hand g1t an outcome, and a fleet of agents converges
20it onto `main`, coordinating with each other and with you, with every decision
21on the record.**
22
23Three things only g1t does, and every feature should serve one of them:
24
251. **Outcomes, not pull requests.** The unit people work in is "make onboarding
26 work offline", not branch #4012. A brief becomes a plan of issues with
27 dependencies; agents take them as they unblock; people steer the outcome
The plan says what g1t is for without measuring it against other products28 and see it converge, rather than stopping at the pull request.
Agents as a team: lifecycle, merge queue, billing and a new shell292. **Agents that work as a team.** Agents know what the others are doing, file
30 what they find instead of widening their change, ask and answer each other
31 through the forge, and defer to people. Many agents on one codebase without
32 a human refereeing collisions.
333. **`main` that only ever moves forward.** Every change lands through checks
34 in the combination it will live in (the merge queue), failures go back to the
35 agent that wrote them, and any line can answer "why is this here?"
36
Workspaces own repositories37## Product model
38
Issues and pull requests replace intents and attempts39g1t keeps the two things every engineer already knows, issues and pull
40requests, and changes the assumption underneath them. A forge built for
Agents as a team: lifecycle, merge queue, billing and a new shell41people expects a few changes in flight, each watched by its author. g1t
42expects dozens of agents working at once across a project, each on its own
43issue, all of which have to land on `main`. A person assigns an issue to
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent44g1t and chooses nothing else: not how many agents, and not which
Agents as a team: lifecycle, merge queue, billing and a new shell45model. An issue can still collect more than one pull request (a second
46attempt, or someone's own agent alongside g1t's), and when it does the
47issue records which one was taken.
Workspaces own repositories48
49| Concept | What it is |
50| --- | --- |
Fast pages, required checks on the branch, self-hosted runners, honest incidents51| **Issue** | What should change in a repo: a bug, a feature, a question. Opened by a person, an agent or an integration such as an error tracker. Carries labels, a description that may say what done means (a Definition of done: context, never a gate), comments, and every pull request made for it. What a merge needs is the default branch's required checks: workflow statuses, the same for people and agents. |
Issues and pull requests replace intents and attempts52| **Pull request** | A proposed change in its own Artifacts fork, made by an agent or a person, usually for an issue. Any number can be open for one issue. Starts as a draft; marked ready; merged or closed. |
53| **Session** | The agent's full context for a pull request: prompt, messages, tool calls, cost. Stored with the pull request and linked from every commit it produced. |
54| **Compare view** | Every pull request for an issue side by side with diff, check results, conflicts against main and against each other, and a reviewer agent's summary. |
55| **Merge** | A person or a policy picks a pull request. A per-repo merge queue lands it. The issue closes, recording which pull request resolved it; the others for that issue close as superseded, or are rebased by their agents when the issue is kept open. |
56
57Issues and pull requests share one sequence of numbers per repository, so
58`#12` names exactly one of them.
Workspaces own repositories59
60Features that fall out of the model:
61
62- **Why-blame.** Click a line and see the prompt and reasoning that produced
63 it, not only the commit.
Issues and pull requests replace intents and attempts64- **Overlap radar.** Pull requests that touch the same files are flagged
65 while the agents are still working, and the agents are told.
66- **Live lanes.** Watch every pull request progress in real time.
67
68## Why issues and pull requests, not something new
69
70An earlier version of this plan merged the two into one new object, an
71"issue" holding "pull requests". That was wrong, for three reasons.
Workspaces own repositories72
Issues and pull requests replace intents and attempts73- **Issues come from everywhere.** People file them, agents file them, and
74 Sentry files them. Most are never worked on by whoever opened them. They
75 need their own life: labels, triage, discussion, closing as not planned.
76- **"Which change did we take?" needs two objects.** When five agents each
77 propose a change, the answer has to be recorded somewhere other than the
78 five proposals. On g1t it is on the issue: `resolved by #14`.
79- **Nobody should have to learn a word to use the product.** An engineer who
80 has used any forge can use g1t on the first day, and finds the agent
81 features where they would look for them.
Workspaces own repositories82
Issues and pull requests replace intents and attempts83What g1t adds to the familiar pair:
Workspaces own repositories84
Agents as a team: lifecycle, merge queue, billing and a new shell85- **Several pull requests per issue is supported**, not an accident. It
86 is the exception, for a second attempt or a competing one, but when it
87 happens the issue's page lists them with their state, and merging one
88 closes the issue with that pull request recorded and the others marked
89 superseded.
Issues and pull requests replace intents and attempts90- **A pull request can be part of the work.** Merging with "keep the issue
91 open" leaves the issue and its other pull requests alone.
92- **Every pull request has a fork and a session.** See
93 [forks and branches](https://docs.g1t.sh/concepts/forks/).
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar94- **Labels need no setup.** A repository starts with the default labels
95 (`bug`, `documentation`, `enhancement`, `question`, `dependencies`,
96 `security` and the rest), each with a color and a description, on issues
97 and pull requests alike; someone with Triage makes a new one as they use
98 it. **Milestones** gather issues and pull requests under a goal and a
99 due date. Pull requests can merge into any branch; the default branch's
100 protection holds only for those into it.
Pull requests from branches101- **The developer path is unchanged.** Push a branch, open a pull request
102 from it, get review, merge. Agents get a fork per pull request instead.
Workspaces own repositories103- **Both paths meet at `main`.** The same landing rules apply to a person's
Issues and pull requests replace intents and attempts104 pull request and an agent's.
Workspaces own repositories105
106## Converging on main
107
Issues and pull requests replace intents and attempts108Twelve issues started together will finish at different times and touch
Workspaces own repositories109overlapping code. Getting them all into `main` without a person refereeing
110is the hard part, and it is handled in four places.
111
1121. **Before work starts: plan the overlap away.** A project is a graph of
Issues and pull requests replace intents and attempts113 issues. A planner agent can split a large goal into issues, predict
Workspaces own repositories114 which files each will touch, and add a dependency where two would collide,
115 so one starts from the other's result instead of from `main`.
Issues and pull requests replace intents and attempts1162. **While agents work: overlap radar.** Each pull request's changed files and
117 symbols are tracked as it pushes. When two pull requests from different issues
Workspaces own repositories118 enter the same area, both agents are told what the other is doing there.
Issues and pull requests replace intents and attempts1193. **When `main` moves: the author resolves.** Every open pull request is
120 trial-merged against the new `main`. A clean merge updates the pull request
121 silently. A conflict resumes that pull request's agent with its original
Workspaces own repositories122 session and the incoming change, so the conflict is resolved by the agent
123 that wrote the code and still knows why.
Issues and pull requests replace intents and attempts1244. **At landing: a speculative queue.** Approved pull requests enter the
125 repo's queue. g1t builds the combined states (`main`+A, `main`+A+B, …) and runs
126 their checks in parallel. Pull requests land in order as their combined state
Workspaces own repositories127 passes; one that fails is ejected back to its agent and the states behind
128 it are rebuilt. `main` only ever receives a state that passed.
129
130Landing can be fully automatic: a repo policy such as "checks pass and the
Issues and pull requests replace intents and attempts131reviewer agent approves" merges without a person.
Workspaces own repositories132
133## Agents aware of each other
134
Issues and pull requests replace intents and attempts135Each repo keeps a live **work registry**: for every running pull request, its
136issue, a running summary of what it has done, and the files and symbols it
Workspaces own repositories137has touched or plans to touch. Agents use it through MCP tools; g1t also
138acts on it without being asked.
139
Issues and pull requests replace intents and attempts140- **Before starting.** When an issue is opened, or an agent is about to
141 begin a task, g1t searches open issues and running pull requests for the same
Workspaces own repositories142 goal (by meaning, not wording) and for the same area of code. If a match
143 exists the agent is told who is on it and how far along, and chooses: join
144 as a deliberate racer, wait for the result, or drop the task. Duplicate
Issues and pull requests replace intents and attempts145 issues are offered for merging.
Workspaces own repositories146- **Finding out-of-scope work.** An agent that discovers something outside
Issues and pull requests replace intents and attempts147 its issue asks the registry who works there. If another pull request owns that
Workspaces own repositories148 area, it **hands off**: a note, the relevant excerpt of its session, and
149 optionally commits the receiver can take. If nobody does, it opens a child
Issues and pull requests replace intents and attempts150 issue instead of widening its own change.
151- **Asking.** An agent can put a question or a request to another pull request.
Workspaces own repositories152 The receiver gets it at its next turn.
Issues and pull requests replace intents and attempts153- **Waiting.** An agent that needs another pull request's result parks itself.
Workspaces own repositories154 Its sandbox sleeps, spend stops, and it resumes from the new state when
Issues and pull requests replace intents and attempts155 that pull request merges.
Workspaces own repositories156- **Agents that do not cooperate.** For pushes from tools that never call
Issues and pull requests replace intents and attempts157 these tools, g1t compares the pushed change against running pull requests and
Workspaces own repositories158 flags near-duplicates itself.
159
160Every handoff, question and wait has a state (offered, accepted, declined,
161done), appears in the timeline, and is visible to people. A handoff declined
162twice, or two agents passing work back and forth, goes to the "needs you"
163inbox.
164
165## Review at scale
166
167Cloudflare's brief asks "how do you review everything they produce?". With
168hundreds of agents, a person cannot read every diff, so review is by
169exception.
170
Issues and pull requests replace intents and attempts171- **Evidence, not diffs.** Every pull request carries a proof bundle: checks run
Workspaces own repositories172 and their output, a preview URL, a plain-language summary, and the
173 behaviour that changed.
Issues and pull requests replace intents and attempts174- **Two agent reviewers.** One reviews the change against the issue. A
Workspaces own repositories175 second is adversarial: it tries to break the change and reports what it
176 found.
177- **Risk tiers.** Each change is scored from what it touches, how large it
Issues and pull requests replace intents and attempts178 is, and how the reviewers ruled. Low risk merges on policy; high risk goes
Workspaces own repositories179 to a person with the evidence already assembled.
Issues and pull requests replace intents and attempts180- **Trust is earned.** An agent's record on a path (merged, reverted, caught
Workspaces own repositories181 by review) raises or lowers the tier its changes land in.
Issues and pull requests replace intents and attempts182- **Sampling.** A share of auto-merged changes is sent to a person anyway,
Workspaces own repositories183 to keep the policy honest.
184
185## Rethinking the git primitives
186
Issues and pull requests replace intents and attempts187- **No branches for agents.** A pull request is a fork; `main` is the only
Workspaces own repositories188 long-lived line. There is nothing to name, clean up or go stale.
Issues and pull requests replace intents and attempts189- **Projected main.** New pull requests start from `main` plus everything already
Workspaces own repositories190 in the landing queue, so they are built on the state they will land on.
191- **Structural merge.** The merge engine merges by syntax tree, not by line,
192 for supported languages. Two agents adding different functions to the same
193 file do not conflict.
194- **Forkable sessions.** A session can be forked at any turn: the code as it
195 was at that moment plus the conversation up to it, continued with a
196 different instruction. Branching applies to the reasoning as well as the
197 code.
Issues and pull requests replace intents and attempts198- **Provenance in history.** Every commit records its issue, session,
199 agent, model and cost, and is signed with a key issued to that pull request. The
Workspaces own repositories200 history can be audited by machine.
201
202## People in the loop
203
204### Code that arrives from outside
205
206People will keep pushing with plain git, their editor, or another tool. Every
207push goes through g1t's git front end, so none of it bypasses the model.
208
Issues and pull requests replace intents and attempts209- **A push to a branch becomes a pull request.** g1t adopts it with the pusher as
210 author. A reviewer agent writes the issue it appears to serve and offers
211 to attach it to an open issue it matches. From there it gets the same
212 checks, compare view and queue as agent work.
Workspaces own repositories213- **A push to `main` follows repo policy.** Protected: refused with a message
214 saying which ref to push to instead, so it enters the queue. Open: accepted
215 and treated as "`main` moved", which re-verifies the queue and triggers
Issues and pull requests replace intents and attempts216 resolve-on-move for every open pull request.
Workspaces own repositories217- **Context is an open format.** A commit trailer names the session that
218 produced it, so any tool can attach its transcript. Commits without one are
219 shown in why-blame as "pushed by a person, no session".
Issues and pull requests replace intents and attempts220- **Approval rules.** Per repo and per path: merge automatically, require a
Workspaces own repositories221 named person, or require a person when the change is large or the reviewer
222 agent is unsure.
223
224### Joining work that is already running
225
226- **Every session has a live page** that works on a phone: the transcript as
227 it streams, the current diff, check results.
228- **Steer.** Send a message, pause, or redirect. Hosted agents receive it
229 immediately; a person's own Claude Code receives it at its next turn
230 through the CLI hooks.
231- **Answer.** When an agent is blocked on a question, it appears in a "needs
232 you" inbox and as a notification. The answer resumes the agent.
Issues and pull requests replace intents and attempts233- **Take over and hand back.** Check out the pull request's fork, commit by hand,
Workspaces own repositories234 push, and let the agent continue from there.
235
236### Planning by writing
237
238- **Brief.** Write the outcome in prose on the site, or commit it as a
Fast pages, required checks on the branch, self-hosted runners, honest incidents239 markdown file. A planner agent turns it into a project: issues, each with
240 what done means, and dependencies. The person edits the graph before anything starts.
Workspaces own repositories241- **Plan from their own agent.** The same operations are MCP tools, so a
242 person can plan in their own Claude Code session and create the project
243 from there.
244- **The brief stays the source of truth.** Editing it later re-plans: new
Issues and pull requests replace intents and attempts245 issues are added, obsolete ones are closed.
Workspaces own repositories246
247### Seeing what moved
248
Issues and pull requests replace intents and attempts249- **Project page.** The outcome, the issue graph coloured by state, and how
Fast pages, required checks on the branch, self-hosted runners, honest incidents250 many of its issues have landed with their required checks passing,
251 compared with when the project started.
Workspaces own repositories252- **Digest.** An agent-written summary per project and per person: what
Issues and pull requests replace intents and attempts253 merged, what is blocked on whom, which conflicts were resolved, what it
Workspaces own repositories254 cost.
Issues and pull requests replace intents and attempts255- **Timeline.** Every event (push, steer, check, conflict, merge) in order,
Workspaces own repositories256 each linked to the session and the person or agent behind it.
257
258## One session, any surface
259
260A session belongs to g1t, not to the device it started on. The browser, a
261phone and Claude Code are views of the same session.
262
263- **Browser and phone.** The site is a responsive, installable web app with
264 push notifications. Everything a person does (brief, steer, answer,
Issues and pull requests replace intents and attempts265 approve, merge) works there.
Workspaces own repositories266- **Claude Code.** Through `mcp.g1t.sh` and the CLI hooks, a local session is
267 a g1t session: its transcript syncs as it runs and it appears in mission
268 control like any other.
269- **Moving a session.** A local session can be sent to the cloud: a hosted
270 agent takes over the fork and the transcript and continues, so the laptop
271 can close. A hosted session can be pulled down: the CLI checks out the fork
272 and resumes it in local Claude Code with its history.
273- **Limit.** A session running only on a laptop stops when the laptop does.
274 It can be steered between turns but not continued until it is moved or the
275 laptop is back.
276
277## For people who do not write code
278
279- **Documents are first-class.** Specs, guides, policies and decisions live
Agents work in sessions: bounded, visible, steerable work spun off from chat, with subagents and colleagues in a tree paid by its root; memory with sources and scopes; routines; a workspace budget for every agent; agents file issues for whoever asked280 in Docs, its own mode (docs/WORKSPACE.md, "Docs"), not a tab on a
281 project: rendered pages, edited in the browser like a document, with
282 inline comments, and filtered by the project they are about. "Suggest a change" is an
Issues and pull requests replace intents and attempts283 pull request and "publish" is merge, without git vocabulary.
284- **Document issues.** "Write the onboarding guide for the billing API" is
Fast pages, required checks on the branch, self-hosted runners, honest incidents285 an issue. Its Definition of done is a checklist judged by a reviewer agent
286 instead of a workflow. Agents draft and revise; people comment and approve.
Workspaces own repositories287- **Templates.** Product brief, RFC, decision record. A filled-in template is
288 a brief the planner can turn into a project.
289- **Explain.** Ask about any repo, project or change in plain language and
290 get an answer with links to the code and sessions behind it.
291- **Living documentation.** g1t generates "how this works" pages from the
Issues and pull requests replace intents and attempts292 code and keeps them current. When a merged change contradicts a document,
293 an issue opens to update it.
294- **See it, don't read it.** Every pull request on a deployable repo gets a
295 preview URL (Workers Builds from the pull request's fork), so an approver clicks
Workspaces own repositories296 through the result instead of reading a diff. Changes are also summarised
297 in plain language.
Merge main (membership, two-factor, GitHub repo roles) into tokens298- **Roles.** A person can plan and approve work without ever cloning a
299 repo. The roles that were sketched here map onto the five repository
300 roles that are built (see "Access" under what is built): a viewer is
301 Read, a commenter is Read (anyone with Read opens issues and comments),
302 a planner is Triage (labels, milestones, assigning, closing) or Write
303 where planning spends compute, and an approver is Write (reviews count
304 and merges). Workspace-wide, a member may also be a billing manager or a
305 security manager.
Workspaces own repositories306
307## The macro view
308
309The hierarchy above a single repo:
310
311| Level | What it is |
312| --- | --- |
313| **Workspace** | A company or team: its people, repos, agents, budget and policies. |
314| **Initiative** | A business outcome with an owner and measurable results, e.g. "move billing to usage-based pricing". Spans any number of repos. |
Plan: Projects, the home of everything about running software315| **Outcome** | One deliverable inside an initiative: a brief and its graph of issues (shown as **Plan**). Called "project" before 2026-10-04; that name now means what [Projects](#projects) describes. |
Issues and pull requests replace intents and attempts316| **Issue / Pull request** | As above. An issue may touch several repos; a pull request for it then holds one fork per repo and they land together. |
Workspaces own repositories317
Agents as a team: lifecycle, merge queue, billing and a new shell318How it feeds up, and what is built:
319
320- **A workspace is the unit everything belongs to.** Repositories, people,
321 access tokens, and later projects, budgets and policies are the
322 workspace's, never a person's. An account owns nothing; its first step
323 after confirming its email is creating a workspace, and the site sends it
324 there from wherever it was going.
325- **One namespace.** Usernames and workspaces share one set of names, as on
326 Docker Hub and npm. A username is reserved for its owner's workspace, so
327 `g1t.sh/<name>` never means two things.
328- **The workspace page is the roll-up.** `g1t.sh/<workspace>` shows its
329 repositories with their open issues and pull requests, and the pull
330 requests in progress across all of them. Projects and initiatives will
331 roll up to the same page. Its own pages live under `/<workspace>/-/`
332 (people, access tokens, settings), which no repository can be named.
333- **Workspace access tokens instead of service accounts.** A workspace has
334 tokens of its own, in the same table and code path as personal ones. One
Docs and plan: fine-grained tokens, workspace token rules, workflow files, workspace token Write335 acts as the workspace, with a member's rights in that workspace only (the
336 Write role on its repositories; Admin only when an owner ticks it at
337 creation, `access_tokens.admin`, identity/0034), records who made it and
338 when it was last used, and keeps working when that person leaves. CI,
339 integrations and automations use these. Until 2026-10-08 the code gave
340 them Admin on every repository, which the security audit found let any
341 workspace token manage webhooks; code, this plan and the docs now agree.
Agents as a team: lifecycle, merge queue, billing and a new shell342
Workspaces own repositories343### Portfolio
344
345One page answers "where is the business" across every initiative:
346
347- **Health** per initiative: on track, at risk, or blocked, derived from
Issues and pull requests replace intents and attempts348 facts (checks passing, issues stalled, questions waiting on a person),
Workspaces own repositories349 not self-reported.
Fast pages, required checks on the branch, self-hosted runners, honest incidents350- **Progress** as measurable results: required checks passing, issues
Issues and pull requests replace intents and attempts351 merged out of planned, and the trend since the start.
Workspaces own repositories352- **Forecast** from actual throughput: at the current rate, when the
Issues and pull requests replace intents and attempts353 remaining issues land.
Workspaces own repositories354- **Spend** in tokens and dollars against a budget, per initiative.
355- **Waiting on people**: every decision or approval a person owes, by name.
356- **Roadmap**: initiatives laid out as now, next, later, with optional
357 time-boxed cycles for teams that work in sprints.
358
359### Status without asking
360
361- **Standup.** An agent writes a daily report per initiative and one for the
Issues and pull requests replace intents and attempts362 whole workspace: what merged, what changed direction, what is at risk and
Workspaces own repositories363 why, what needs a person. Delivered by email or webhook.
364- **Ask.** A question box over the full event log and all sessions: "what
365 happened on the billing migration since Monday?" answers with links to the
366 sessions and commits behind each claim.
367
368### Long-running agents
369
370Work that runs for days needs supervision that does not depend on someone
371watching.
372
Issues and pull requests replace intents and attempts373- **Checkpoints.** A long pull request reports milestones against its issue, so
374 progress is visible before anything merges.
375- **Stall and drift detection.** A pull request with no meaningful progress, or
376 whose changes have wandered away from its issue, is flagged and can be
Workspaces own repositories377 stopped or re-briefed automatically.
Issues and pull requests replace intents and attempts378- **Budgets.** Hard limits on spend and time per pull request, project and
Workspaces own repositories379 initiative.
380
381### Context hub
382
383Agents working across repos and days need context that outlives any one
384session and reaches beyond the code. The context hub is one place an agent
385asks, whatever the source.
386
387| Source | What it holds | How it gets there |
388| --- | --- | --- |
389| **Memory** | Decisions, conventions, gotchas, facts about systems | Written by agents and people in g1t |
390| **Code and sessions** | The repos, and the reasoning behind every change | Already in g1t |
391| **Connected sources** | Jira and Linear tickets, Notion and Confluence pages, Google Drive documents, Slack threads, Sentry issues | Connectors, authorised per workspace |
392
393How it behaves:
394
395- **One search.** An agent asks a question and gets ranked results across
396 all sources, each labelled with where it came from, who wrote it, and how
397 fresh it is.
398- **Connected sources stay where they are.** g1t indexes them for search and
399 fetches the current version when an agent opens one. The external system
Issues and pull requests replace intents and attempts400 remains the source of truth, and a link placed on an issue ("see
Workspaces own repositories401 JIRA-482", a Notion URL) is pulled into the agent's starting context.
402- **Permissions carry over.** A connector only exposes what the connecting
403 account can see, and a workspace admin chooses which spaces, projects or
404 channels are included.
405- **External content is untrusted.** A ticket or page can contain text meant
406 to manipulate an agent. It is marked as reference material, never treated
407 as instructions.
408- **Documentation is separate.** Context is what agents know; documentation
409 is what people read, and it is generated from context and code.
410
411Memory is the part of the hub that g1t owns and agents write to:
412
413- **Memory is written freely.** Any agent or person adds an entry with one
414 call: a decision, a convention, a gotcha, a fact about a system. No review
415 gate. Each entry records who wrote it, from which session, and when.
416- **It is still a repository.** Each workspace has a memory repo in
417 Artifacts, so every write is a commit: versioned, attributable, and
418 revertible.
419- **It is kept healthy by an agent.** A consolidation agent merges
420 duplicates, retires entries that newer ones contradict, and flags
421 conflicts it cannot settle. People can pin an entry (agents may not change
422 it), correct it, or retract it.
423- **Agents read it.** Every session starts with the context relevant to its
Issues and pull requests replace intents and attempts424 issue, found by search, and can query more through MCP.
Workspaces own repositories425- **Updates are events.** A memory write or a change in a connected source
426 is an event, so "when context changes, update the affected docs" is an
427 automation, on by default.
428- **It is scoped inside the workspace.** Some context applies to the whole
429 workspace, some to one initiative, project or repo, so an agent gets what
430 applies to its work.
431- **It never crosses workspaces.** A workspace is the isolation boundary: its
432 context, sessions and private repos are invisible to every other
433 workspace, and an agent's token is bound to one workspace.
434
435## Working in g1t
436
437- **Mission control.** The signed-in home page: every running session, every
Issues and pull requests replace intents and attempts438 issue waiting on a decision, and what merged, across all repos.
Plan: Projects, the home of everything about running software439- **Outcomes.** Group issues across repos toward one result and track how
440 many are open, racing, or merged. (What [Projects](#projects) means is
441 below.)
Issues and pull requests replace intents and attempts442- **Steering.** Send a message to a running pull request, or to all pull requests on an
443 issue at once, without stopping them.
Workspaces own repositories444- **Automations.** Rules that start work without a person (next section).
445
446## Automations and integrations
447
Sidebar: the panels really slide448> **2026-10-03:** g1t's own `.g1t/automations` format was built and then set
449> aside at the user's request ("let's just copy GitHub Actions on that for the
450> time being"). Automation on g1t is GitHub Actions workflows in
451> `.g1t/workflows/`; the format below is kept for later.
452
Workspaces own repositories453An automation is **when** an event happens, **if** conditions hold, **do**
454something. They are defined as files in the repo (`.g1t/automations/`), the
455way GitHub Actions workflows are, and can also be built in the UI.
456
457### Events that can trigger one
458
459| Source | Examples |
460| --- | --- |
Issues and pull requests replace intents and attempts461| Git | push, merge, check failed, `main` moved |
462| g1t | issue opened, pull request stalled, context updated, handoff declined, budget reached |
Workspaces own repositories463| Time | cron schedule |
464| Integrations | Sentry issue, PagerDuty incident, Linear or Jira ticket, Slack message or mention, GitHub issue, Stripe event |
465| Anything else | a signed generic webhook, or an email to a per-repo address |
466
Issues and pull requests replace intents and attempts467**Actions**: open an issue (optionally assigning N agents to it), message
468a running pull request, update documentation, notify, call a
Workspaces own repositories469webhook, write back to the source system.
470
471**Example: Sentry.** A new production error arrives. The automation opens an
Issues and pull requests replace intents and attempts472issue labelled `bug`, with the stack trace, release and frequency in its
473description. Why-blame
Workspaces own repositories474finds the session that wrote the failing line, so the fixing agent starts
Issues and pull requests replace intents and attempts475with the original reasoning. When the fix merges, g1t comments on the Sentry
Workspaces own repositories476issue and resolves it.
477
478### Rules every automation obeys
479
480- **Deduplication.** The same Sentry issue firing 500 times maps to one
Issues and pull requests replace intents and attempts481 issue.
Workspaces own repositories482- **Limits.** Concurrency and budget caps per automation.
483- **Loop protection.** Work started by an automation cannot retrigger the
484 same automation without a person in between.
485- **External input is untrusted.** A webhook payload can contain text written
486 by an attacker. Agents started by external events run with reduced
Issues and pull requests replace intents and attempts487 permissions and cannot merge without the repo's approval rule passing.
Workspaces own repositories488
489**Checks** are the other half of what GitHub Actions does: build and test
Issues and pull requests replace intents and attempts490commands declared in `.g1t/checks.yaml`, run in sandboxes on every pull request
Workspaces own repositories491and on every combined state in the landing queue.
492
Docs and plan: fine-grained tokens, workspace token rules, workflow files, workspace token Write493### Tokens, scopes and packages the GitHub way (built 2026-10-08)
494
495> **2026-10-08 (owner):** "emulate all of what GitHub does for scope
496> mapping and packages." GitHub's current behaviour is the spec.
497
498This **reverses identity/0023**, which retired a token's reach to some
499workspaces or repositories and left classic tokens only. The reason it is
500reversed: the owner chose GitHub parity, and GitHub has fine-grained tokens
501beside classic ones, with workspaces (organizations) governing both.
502
One kind of access token; presence and status; usernames keep their case; the tour is a miniature of the real app; icons for password managers503> **2026-10-09 (owner): one kind of token.** "We don't need classic and
504> fine-grained tokens ... not 2 different implementations we don't need to
505> maintain." identity/0041 folds both into one access token: a level per
506> resource (each level *is* a scope, so every check below reads scopes
507> unchanged), a reach (all your workspaces, one workspace with all,
508> selected or only public repositories, or none), an owner (a person or a
509> workspace) and an expiry. `TokenKind` and `g1t_contracts::fine_grained`
510> are gone; the reach type is `TokenReach`. The governance below now reads
511> "allow tokens for all workspaces" and "allow tokens for this workspace".
512> The history below is kept for why.
513
Docs and plan: fine-grained tokens, workspace token rules, workflow files, workspace token Write514- **Fine-grained personal access tokens** (identity/0034,
515 `services/identity/src/token_reach.rs`, `g1t_contracts::fine_grained`):
516 one resource owner (a workspace the person belongs to, or their own
517 account), all, selected (up to 50, by repository id) or only public
518 repositories, and a level per permission under GitHub's names (contents,
519 metadata, issues, pull_requests, actions, workflows, checks, statuses,
520 deployments, pages, environments, secrets, variables, webhooks,
521 administration, packages, security_events; members,
522 workspace_administration, self_hosted_runners, workspace_secrets,
523 workspace_webhooks, workspace_billing, models; email_addresses, starring,
524 notifications; g1t's agents and memory). Each level maps onto g1t's
525 scopes, which the token stores, so every check that reads scopes
526 (`scopes::decide` for the API and MCP, `decide_git`, `decide_packages`)
527 reads them unchanged. They must expire, within 366 days. On each use,
528 identity cuts the resolved person down to the token's reach
529 (`apply_reach`); `access::granted` gives no role outside it, so a public
530 repository elsewhere still reads and nothing more.
531- **Governance** (`token_policies`, `token_workspace_revocations`): per
532 workspace, allow classic, allow fine-grained, require approval (on by
533 default, as GitHub's; owners' own tokens never wait), the longest
534 lifetime, and forbidding tokens that never expire. Owners see every
535 member's token that can reach the workspace, approve or deny pending
536 fine-grained ones (inbox: `token.approval_requested` and
537 `token.approval_reviewed`, the inbox's first notices about no
538 repository), and revoke one there. REST and MCP for owners; audited as
539 `token.*`.
540- **Workflow files** need `workflow_files:write` (GitHub's `workflow`
541 scope; the `workflows` permission) from any token, checked commit by
542 commit on push (`services/repos/src/workflow_gate.rs`) and on files g1t
543 writes for a token. A job's token never has it. g1t's agents push with
544 run credentials, not tokens, and are not gated by it; their work arrives
545 as pull requests people review.
546- **Workspace tokens** have Write unless an owner gives Admin at creation.
547- **Deploy keys** (identity/0035): per repository, read-only unless write
548 is ticked; resolved to a principal bound to the one repository.
549 Serving git over SSH is still to come, so nothing uses them yet.
Merge packages: roles, Actions access, source label, soft delete, API550- **Packages** (packages/0006, `services/packages/src/access.rs` and
551 `settings.rs`): per-package roles (read, write, admin) for people and
552 teams, with "inherit access from the linked repository" (on by default);
553 "Manage Actions access", which a job's token is held to (its own linked
554 repository writes; any other repository needs an entry, added
555 automatically for the repository whose job first publishes an unlinked
556 package); linking by `org.opencontainers.image.source` (manifest
557 annotation or image label, same workspace, pusher may push there); 30-day
558 soft delete of packages and versions, registry deletes included (the name
559 and version stay reserved), restore, and a purge in the hourly cron; a
560 settings tab and a "Deleted packages" view; 17 REST operations and one
561 `package` MCP tool (reads `packages:read`; settings and access
562 `packages:write` with the package's Admin role; delete and restore
563 `packages:delete`); and download counts per version in every registry.
564 Existing unlinked packages have no Actions access entries, so workflows
565 that used them through `G1T_TOKEN` need one added.
Docs and plan: fine-grained tokens, workspace token rules, workflow files, workspace token Write566
Merge branch 'worktree-agent-a3abfcce648e87dca'567### Keeping workflow runs safe (built 2026-10-08)
568
569An audit of g1t Actions found a job's token was a full-access workspace
570token, environments had no protection, outside pull requests ran at once,
571the cache could be poisoned across branches, a job's token could set off
572more runs, and masking missed multi-line and encoded secrets. Now:
573
574- **The job's token** (`G1T_TOKEN`, `GITHUB_TOKEN`) is minted per job by
575 identity (`create_job_token`, migration identity/0030): it reaches its
576 repository only (`TokenAccess.repo`, enforced by the API, git and the
577 registries), carries the scopes its `permissions:` map to
578 (`g1t_actions::permissions`), is revoked when the job ends, and its
579 writes are audited with the run as `run_kind: workflow_job`. Without
580 `permissions:` it gets the repository's default, the GitHub way:
581 repositories that existed when actions/0007 ran keep read and write,
582 newer ones take their workspace's default (read-only unless an owner
583 says), and a workspace can cap every repository at read-only. An outside
584 pull request's is read-only. "Allow g1t Actions to create and approve
585 pull requests" (repository and workspace, off by default) decides whether
586 the token may open or approve pull requests. OIDC (`id-token: write`)
587 reads the same permissions model.
588- **No loops.** Work and repos mark the events a job's token causes
589 (`causedByJob`), carried on to a pull request it moves; the actions
590 service starts nothing for them. `workflow_dispatch` and
591 `repository_dispatch` (now sent by `POST {repo}/dispatches`) still start
592 runs.
593- **Environments' protection rules** (actions/0007): required reviewers
594 (people or teams, up to six, optionally not whoever started the run), a
595 wait timer, which branches and tags may deploy, and admin bypass. A job
596 naming one is `pending` once its needs are done, its environment read
597 then (an expression included); reviewers hear in the inbox
598 (`deployment.review_requested`) and approve on the run's page or through
599 `pending_deployments`; secrets are read only when the job starts.
600- **Approval for outside pull requests**, by a repository policy
601 (first-time contributors, outside contributors (the default), or every
602 external contributor): such runs are `action_required` until someone with
603 Write approves them.
604- **The cache is scoped by ref** (own, then the pull request's base, then
605 the default branch; outside pull requests save where nothing else reads)
606 and versioned by its paths and compression (0006's toolkit `version`,
607 which g1t's runner now sends too); g1t's `actions/cache` and the
608 toolkit's protocols share one scope rule. Entries from before were
609 expired.
610- **Masking** covers each line of a multi-line secret, base64 at every
611 offset and JSON-escaped forms; outputs holding a secret are withheld and
612 annotations masked.
613- A job's own `concurrency:` is honoured, `create` runs on new branches and
614 tags, and `on: delete` says plainly that it never runs yet.
PLAN.md: blank line before Docker in workflow jobs615
Merge branch 'main' into actions-toolkit-oidc-artifacts616### Docker in workflow jobs (built 2026-10-08)
617
618> **2026-10-08:** "Why didn't we give CI docker then? We need GitHub
619> Actions functionality maxxed baby but with all the good good security
620> etc." The trigger: `deploy.yml`'s runner-image job needs `docker build`
621> and `docker push`, and failed on hosted runners.
622
623**What Cloudflare Containers allow** (their FAQ, updated 2026-10-05, and
624the Docker-in-Docker guide and example it links):
625
626- Docker runs inside a container: `docker:dind`, with `dockerd` as
627 **root**. A rootless Engine does not start there.
628- **No iptables**: `--iptables=false --ip6tables=false`, or the Engine
629 fails setting up its rules. Containers with the `durable_object`
630 scheduling policy (ours: each sandbox is a Durable Object's) cannot turn
631 IP forwarding on either: `--ip-forward=false`, or the Engine exits.
632- So **a bridge network has no way out**: the guide's answer is
633 `--network=host` for `docker run` and `docker build`, which gives
634 containers the outer container's network.
635- Built images and containers are lost when the sandbox stops.
636
637**What was found by trying** (Docker Engine 29.8.2 in a privileged
638container standing in for a sandbox, with the same flags):
639
640- `--bridge=none` makes BuildKit's `RUN` steps fail outright ("network
641 bridge not found"); with the default bridge they run with no route out.
642 Containers default to the bridge too. The default bridge is created
643 fine without iptables, as the FAQ's own example relies on.
644- The overlay snapshotter does not work on an overlay root filesystem, and
645 the containerd image store does not fall back by itself: the Engine
646 starts, then every container fails to mount. Whether a sandbox's disk
647 takes overlays is not documented, so the runner tries a mount first and
648 uses `native` (plain copies) when it fails. `vfs` is not a name the
649 containerd store accepts.
650- `--cpus` and `--memory` need cgroup v2 controllers handed down from a
651 cgroup with no processes, which `docker:dind`'s entrypoint does and a
652 plain `dockerd` does not.
653- A `runc` earlier on the Engine's `PATH` is used both for containers (via
654 containerd's shim) and by BuildKit's executor, with the bundle's
655 `config.json` written before it runs. BuildKit's bridged steps carry
656 libnetwork's `libnetwork-setkey` prestart hook; `RUN --network=none`
657 does not.
658- Buildx skips `type=gha` caches when the job has no GitHub cache service,
659 and the build succeeds without one.
660- Registries' layer hosts: Docker Hub sends layers from
661 `production.cloudfront.docker.com` (and `production.cloudflare.docker.com`),
662 Quay from `cdn0N.quay.io`, Microsoft's from regional
663 `*.data.mcr.microsoft.com`, public ECR from a CloudFront host;
664 `mirror.gcr.io` serves its own.
665
666**What was built** (`crates/runner/src/docker`, `actions/containers.rs`):
667
668- **One Engine per job, started lazily.** The runner listens on
669 `/var/run/docker.sock` itself and starts `dockerd` (root, the flags
670 above, containerd image store, `mirror.gcr.io` first for Docker Hub) on
671 the first connection, or when the job has `services:` or `container:`.
672 A log line says it started and how long it took.
673- **Containers on the job's network.** The socket is an API proxy: a
674 container that asks for a bridge or user network gets `host`; its names
675 (container name, aliases, Compose service, links) resolve to 127.0.0.1
676 in later containers (`ExtraHosts`) and in the job's steps
677 (`/etc/hosts`); `-p 8080:80` is forwarded; `docker inspect` reports the
678 ports as published; `network connect` adds aliases. Sharing the job's
679 network is also what keeps the guardrails on every container: the
680 egress Worker sees their traffic as the job's.
681- **A `runc` shim.** The runner binary, as `runc`: BuildKit steps bound for
682 a bridge lose the network namespace and the libnetwork hook (so they use
683 the job's network); in a guarded job every container (run, exec, build
684 step) gets the egress certificate at `/dev/g1t-egress` and the
685 variables that point tools at it. `/dev` is the container's own tmpfs,
686 so none of it lands in a layer; checked by saving a built image.
687- **Job features:** `services:` (pull, credentials, health waits, logs at
688 the end, `job.services.*`), `container:` (steps and JavaScript actions
689 through `docker exec`, Node mounted from the runner, Alpine falls back to
690 running actions beside it), `docker://` steps and Dockerfile actions in
691 GitHub's `/github/*` layout, `docker/setup-buildx-action` answered
692 natively (the job's Engine is the builder), sign-in to g1t's registry
693 with the run's token.
694- **Kill switch:** the runner Worker's `DOCKER` var (`off`).
695
696**Rejected:** rootless Docker or BuildKit (does not start in Containers);
697Podman or buildah with `vfs` (no better networking, less compatible, slow);
698a standalone `buildkitd --oci-worker-net=host` as the default builder
699(images not in the Engine's store, so `FROM` a just-built image and
700`docker run` of a build fail without `--load` round trips); a `docker` CLI
701wrapper adding `--network=host` (misses Compose, SDKs and testcontainers,
702which speak the API).
703
704**Not yet:**
705
706- Seen on Cloudflare itself: whether a sandbox's disk takes overlays,
707 `--privileged`, and the first deploy's pull of the base from
708 `registry.cloudflare.com` (its layer host may need a workflow-only line).
709- `type=gha` build caches backed by g1t's Actions cache.
710- Multi-platform builds (QEMU's `binfmt_misc` in a sandbox).
711- Docker for agents and checks, not just workflow jobs.
712- `runner-base.yml` on g1t's machines: the base's apt step needs
713 `Acquire::https::CAInfo` pointed at the egress certificate first.
714- A deploy that appends the runner binary as a layer through the registry
715 API, with no Docker and no 3 GB pull.
716
Workspaces own repositories717Agents can also reach integrations directly: an agent definition lists MCP
718servers (Sentry, Linear and so on) it may use while working.
719
Actions: OIDC tokens, the toolkit's cache and artifact services, and artifacts in R2720### Workflows: the toolkit, OIDC and artifacts
721
722> **2026-10-08:** built so that workflows that deploy, cache and pass files
723> run unmodified.
724
725- **The toolkit's services.** Every job gets `ACTIONS_RUNTIME_TOKEN` (a
726 JWT whose `scp` names its run and job, signed with a key derived from
727 the job's own token, so nothing new is kept), `ACTIONS_RESULTS_URL`,
728 `ACTIONS_CACHE_URL` and `ACTIONS_CACHE_SERVICE_V2`. The API answers the
729 cache's Twirp service (v2) and its older REST protocol, the artifact
730 Twirp service, and the signed blob links they hand out (a subset of
731 Azure Blob's protocol mapped onto R2 multipart uploads), from the same
732 cache and artifact rows g1t's own runner uses. As the clients' source
733 reads, `@actions/cache` and `@actions/artifact` treat any server
734 but github.com as GitHub Enterprise Server, so the cache client speaks
735 the older protocol and the artifact client refuses to run. g1t's runner
736 therefore keeps handling `actions/upload-artifact`, `download-artifact`
737 and `upload-artifact/merge` itself; the Twirp artifact service is there
738 for clients that do not check.
739- **OIDC.** The issuer is `{API}/actions/oidc`, the API's own host, with
740 discovery, JWKS (RFC 7638 `kid`s, a previous key published while
741 rotating) and a token endpoint for `core.getIDToken`. Claims follow
742 GitHub's. A job gets one only when its permissions (or its workflow's)
743 give `id-token: write`, and never for an untrusted run. The permission
744 check reads only `id-token` (`services/actions/src/runtime.rs`,
745 `id_token_permitted`), the seam for the full `permissions:` model.
746- **Artifacts** moved from KV to R2 (`a/` in the cache bucket), with rows
747 in the actions service: numeric ids, 5 GiB each and 10 GiB a run,
748 zipped by the runner, `retention-days` up to the repository's setting
749 (1 to 90, 14 by default), `overwrite`, `compression-level`, patterns,
750 merging and other runs of the same repository. The REST artifacts API and
751 the `workflow` tool's artifact actions follow GitHub's shapes; the run's
752 page lists them with size and expiry, with download and delete. Their
753 storage is charged with the cache's.
754- **Later:** the toolkit's older artifact protocol (`upload-artifact@v3`
755 inside other actions), downloads from other repositories, and npm
756 trusted publishing, which depends on npm accepting g1t's issuer.
757
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts758### Actions parity: other repositories, triggers, step timeouts (built 2026-10-08)
759
760- **Other repositories' actions and reusable workflows**
761 (`services/actions/src/reach.rs`, actions/0008): `uses: owner/repo@ref`,
762 `owner/repo/path@ref` and `jobs.<id>.uses: owner/repo/.g1t|.github/workflows/x.yml@ref`
763 are looked for on g1t first, as the calling workspace sees them. Same
764 repository or public: used. Private: only from a private repository of
765 the same workspace, when its **Settings → Actions → Access** (`access_level`,
766 `GET`/`PUT …/actions/permissions/access`, MCP `get_access`/`set_access`)
767 says `organization`; a job fetches such an action with a read-only token
768 for that repository, revoked with the job (`job_action`, the runner's
769 `POST /actions/jobs/{job}/action`). Not on g1t: actions from GitHub as
770 before, reusable workflows from a public GitHub repository. A `./` call
771 inside a called workflow reads from that workflow's own repository.
772- **Secrets for called workflows** follow GitHub: none but the job token
773 unless the caller passes `secrets:` by name or `secrets: inherit`;
774 required secrets are checked before the call; a called job's
775 `environment:` reads that environment's secrets over what was passed. The
776 mapping is kept with the called jobs and read when each starts, so no
777 secret is stored. (Before, same-repository called workflows read every
778 repository secret.)
779- **Triggers:** `release` (created, published, released, prereleased,
780 edited, unpublished, deleted; repos now publishes `release.*`),
781 `deployment` and `deployment_status` (from the deployments service's
782 events; ones an Actions job or a job token made are marked
783 `causedByJob` and start nothing), `pull_request` `reopened` and
784 `converted_to_draft`, `issue_comment` `edited` and `deleted` (work
785 publishes `pull.reopened`, `pull.converted_to_draft`, `comment.edited`
786 and `comment.deleted`).
787- **`timeout-minutes` on every step**, `uses:` included: the runner keeps a
788 step deadline every process it starts stops by, nested composite steps
789 taking the nearer one.
790- **Not yet:** a deployment's `ref` that is neither a branch nor a commit
791 is read as a tag; `on: delete`.
792
Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)793### Runs: summaries, attempts, cancelling, logs and badges (built 2026-10-08)
794
795GitHub Actions parity on the run itself:
796
797- [x] **Job summaries.** The runner sends each step's
798 `$GITHUB_STEP_SUMMARY`, masked, as a `summary` report (1 MiB a step,
799 20 steps a job, kept in `job_summaries`, actions/0009); the run's page
800 renders them as sanitised Markdown, a card per job.
801- [x] **Attempts and re-runs.** A re-run is a new attempt that keeps the
802 one before (`run_attempts`, `job_attempts`; a re-run job's logs and
803 summary move to `{job}.{attempt}`, which is its id when that attempt is
804 viewed). Re-run all, failed, or one job (`POST …/jobs/{job}/rerun`) with
805 the jobs that need it; a matrix or a called workflow runs again whole.
806 Debug re-runs set `RUNNER_DEBUG=1`, `ACTIONS_STEP_DEBUG`,
807 `ACTIONS_RUNNER_DEBUG` and `runner.debug`; the runner then shows
808 `::debug::` lines and how each step's `if:` read. An attempt picker on
809 the run's page, `attempt` on `get_workflow_run` and
810 `…/runs/{id}/attempts/{n}`.
811- [x] **Graceful cancel.** A running job gets `cancel_requested_at`,
812 told in the answer to its next report (a quiet step pings every 10 s):
813 the step's process group gets SIGINT, SIGTERM at 7.5 s, SIGKILL at 10 s;
814 then only `always()`/`cancelled()` steps and post steps run, and the job
815 ends `cancelled`. Hard-stopped after 5 minutes; cancelling again or
816 `…/force-cancel` stops at once.
817- [x] **Logs.** Search on the run's page (matching lines, groups opened);
818 one job's log as text (`…/jobs/{job}/log.txt`, API
819 `…/jobs/{job}/logs?format=text`) and an attempt's as a zip laid out as
820 GitHub's (`…/runs/{id}/logs.zip`, API `…/runs/{id}/logs`), up to 24 MiB.
821- [x] **Status badges** at `/{ws}/{repo}/actions/workflows/{file}/badge.svg`
822 with `branch` and `event`; public repositories' for anyone (cached a
823 minute), private ones' only for viewers who can see them. "Create status
824 badge" on the workflow's page gives the Markdown.
825- Not yet: re-running one combination of a matrix alone; signals into a
826 job container's processes on cancel (they reach `docker exec` only).
827
Merge runner image: Java 21, .NET 8, Ruby 3.3828### Runner image: Java, .NET and Ruby (built 2026-10-08)
829
830The base (`services/runner/base/Dockerfile`) adds Temurin 21, the .NET 8
831SDK and Ruby 3.3, placed where the setup actions look so common workflows
832run unmodified and download nothing:
833
834- **Java** in `RUNNER_TOOL_CACHE/Java_Temurin-Hotspot_jdk/<semver, + as
835 ->/x64` with `x64.complete`; `JAVA_HOME`, `JAVA_HOME_21_X64` and `PATH`
836 set. `actions/setup-java` (`temurin`, `21`) resolves it from the cache.
837- **.NET** in `/usr/share/dotnet` (setup-dotnet's Linux install dir),
838 owned by `node`; `DOTNET_ROOT` set, telemetry off. `setup-dotnet` with
839 `8.0.x` keeps it while it is the newest 8.0 SDK, else installs beside it.
840- **Ruby** built from source into `RUNNER_TOOL_CACHE/Ruby/<v>/x64` with
841 `x64.complete`, on `PATH`. On Debian, `ruby/setup-ruby` counts as
842 self-hosted and uses only the tool cache, so any version but 3.3 fails
843 (documented in limitations).
844
845**`gh`: not installed.** With `GH_HOST=g1t.sh`, `gh` treats g1t as
846GitHub Enterprise Server: REST under `https://g1t.sh/api/v3` and GraphQL at
847`https://g1t.sh/api/graphql`. Both are 404 today (the API is REST at
848`api.g1t.sh`, and `GITHUB_GRAPHQL_URL` is empty), and `pr`, `issue`, `repo`
849and `run` are GraphQL-first, so even `gh api` alone would need the
850`/api/v3` prefix. Jobs call the API with `curl` and `$GITHUB_API_URL`
851(documented in the Actions guide).
852
853**Later:** to make `gh` useful, `g1t.sh/api/v3/*` proxying to the REST API
854(enough for `gh api` and `gh auth status`), then a GraphQL subset for the
855`pr`/`issue` read paths. Ship `gh` in the base only once those exist.
856More preinstalled Rubies (3.2, 3.4) if workflows ask, at roughly 75 MB
857each. `setup-dotnet@v5` first installs the current LTS .NET runtime (10,
858a 36 MB download) every run before finding SDK 8 already there;
859preinstalling that runtime would skip it.
860
861**Size:** the base went from 3.18 GB to 4.52 GB as `docker image inspect`
862reports it (813 MB to about 1.2 GB compressed): Temurin 308 MB (without
863`src.zip`), .NET 512 MB (without the SDK's translations), Ruby 74 MB,
864headers and ICU 44 MB.
865
Plan: a repository that maintains itself, and deployments on g1t.page866## A repository that maintains itself
867
868> **2026-10-04:** the user asked for Dependabot, GitHub Advanced Security and
869> Vercel-style deployments, "so you're not having to maintain shit and you're
870> just pushing up agents that are delivering work consistently".
871
872GitHub reports problems and leaves the fix to you. In g1t, an agent opens an
873issue for each problem, writes the fix, runs its checks, links a preview and
874lands it through the queue. People only decide.
875
876### Upkeep agents
877
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar878- **Dependency updates.** The file is `dependabot.yml` version 2, read from
879 the default branch at `.g1t/dependabot.yml` (or `.yaml`), then
880 `.github/dependabot.yml` (or `.yaml`); `.g1t/` wins when both exist, and
881 an imported repository's file works unchanged. Every option is read and
882 checked, each problem reported with its line and key on the Security page
883 and as the `g1t / dependabot.yml` status on pull requests that change the
884 file; a file with problems is not acted on.
885 - **Built (2026-10-07):** version updates for npm, cargo, gomod and pip:
886 schedules (all intervals, cron and natural phrases, time zones, a
887 picked time per repository), allow, ignore, cooldown (3 days by
888 default), groups (including across directories and `group-by`),
889 versioning strategies, open-pull-requests-limit, commit-message,
890 branch names, rebase-strategy, assignees, reviewers, private
891 registries filled from workflow secrets (npm, cargo, Go proxy, Python
892 index), and the `@g1t` comment commands. Pull requests come from g1t
893 with an `updated-dependencies` commit record and land through the
894 required checks; one that fails them is closed and becomes a
895 "needs code changes" issue assigned to g1t.
896 - **Security updates follow the same file:** ignore (and comment
897 ignores), allow names, `applies-to: security-updates` groups,
898 commit-message, assignees, reviewers, labels and milestone. Cooldown
899 and the open pull request limit do not apply. The Security updates
900 switch still turns them on and off.
901 - **Labels, milestone and target-branch** are applied to version
902 updates: `dependencies` and the ecosystem's label by default, missing
903 labels created; `target-branch` updates are made from that branch and
904 merge into it.
905 - **Not done yet:** one pull request for a multi-ecosystem group
906 (it opens one per ecosystem); registries that sign in with OIDC;
907 updating vendored copies; and version updates for the other
908 ecosystems (bundler, composer, docker, github-actions, gradle, maven,
909 nuget, terraform, uv and the rest are read and checked only).
Plan: a repository that maintains itself, and deployments on g1t.page910- **Secret scanning.** Pushes are scanned for known token formats. A push
911 that adds a secret is refused with the file and line; one already in
912 history opens an issue to rotate it and remove it.
913- **Vulnerability alerts.** Dependencies are matched against the OSV
914 database. Every alert links to the issue and pull request fixing it.
915- **Code scanning.** A reviewer agent reads each pull request's diff for
916 security problems and leaves findings as review comments with a
917 suggested fix. Findings on `main` open issues.
918- **A security page per repository** lists alerts, secrets and findings,
919 with the agent work on each, like GitHub's Security tab.
920
921All of these are event sources for the existing issue → agent → checks →
922queue pipeline; they need no new kind of work.
923
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar924### The security suite (built 2026-10-07)
925
926GitHub Advanced Security's depth, in g1t's shape (services/security,
927`g1t_contracts::security_suite`, docs `guides/security/*`):
928
929- **Secret protection.** Custom patterns (repository and workspace; Rust
930 `regex`, linear time, size-limited; test strings; dry run over the
931 default branch) used by push protection, `commit_file` and history
932 scans. Bypass with a reason (false positive, used in tests, will fix
933 later), recorded on the alert and in the audit log; delegated bypass
934 (requests reviewed by owners and repository admins, through the inbox).
935 Validity checks for GitHub, GitLab, Stripe, Slack, npm, OpenAI,
936 Anthropic and SendGrid tokens, made by the repos service, which reads the
937 landed secret again: the value never leaves it except to the issuer. AWS
938 keys (need their secret key to sign) and webhook addresses (would post)
939 are the extension points left (`g1t_scan::validity::check_for`).
940- **Code scanning.** SARIF 2.1.0 uploads → alerts with fingerprints (tool
941 partial fingerprints first), fixed when no longer reported; pull request
942 uploads → line comments and the `Code scanning` commit status, gated by a
943 per-repository threshold and required like any check. Starter workflow:
944 a scanner per language present, each uploading its own category: Bandit
945 (Python), gosec (Go), ESLint + eslint-plugin-security with the SARIF
946 formatter (JS/TS), Clippy + clippy-sarif (Rust); all install from the
947 registries the runner's egress already allows. Semgrep's registry rules
948 and the Opengrep rules fork are not usable in a paid feature, so neither
949 is used. "Fix with g1t" opens an issue and runs the agent.
950- **Supply chain.** Dependency graph (direct/transitive where the lockfile
951 says, npm licenses), SPDX 2.3 SBOM, `Dependency review` status on every
952 pull request (OSV severity threshold, license deny list, summary comment).
953- **Overview.** Workspace totals, opened/closed, a daily snapshot trend,
954 coverage, repositories most in need first.
955- **Paid.** The Security and quality activation on private repositories;
956 free on public ones; the free core (secret scanning, push protection,
957 vulnerability alerts, security updates, dependency graph) free everywhere.
958
959Not built yet:
960
961- **The reviewer agent as an analysis source.** g1t's reviewer reads each
962 pull request's diff (`agent_review`), but its findings are review
963 comments, not SARIF. Next: have it emit SARIF for the security issues it
964 finds and upload them as the tool `g1t review`, so they become alerts and
965 count toward the Code scanning check.
966- **Repository security advisories.** Private advisories, draft →
967 published, with affected versions (ranges per ecosystem), severity and a
968 CVSS vector, credits, and a private fork (a `g1t/advisory/GHSA-…` working
969 copy only the advisory's collaborators can see) for the fix, merged into
970 the default branch when the advisory publishes. Published advisories
971 should feed the OSV-shaped data other g1t repositories' vulnerability
972 alerts read. CVE requests are out of scope. Needs: an `advisories` table
973 per repository, a collaborator list per advisory, the private-fork
974 visibility rule in repos, and an Advisories page on the Security tab.
975- **SARIF upload as a background job.** Uploads are read in the request
976 (10 MB encoded, 40 MB unzipped, 5,000 results); larger ones need a queue.
977
Plan: a repository that maintains itself, and deployments on g1t.page978### Deployments
979
980- **A preview for every pull request**, at
981 `<pr>--<repo>--<owner>.g1t.page`, linked on the pull request and updated
982 on each push. `main` deploys to `<repo>--<owner>.g1t.page`, and a
983 repository can add its own domain.
984- **On g1t.page, not g1t.sh,** so customer code never shares cookies or an
985 origin with the site people sign in to.
986- **Built on Workers for Platforms.** Each deployment is a user Worker in a
987 dispatch namespace; one dispatch Worker on `*.g1t.page` routes to it. The
988 build runs in the same runners as Actions. Static sites and Workers apps
989 first; container apps and databases later.
990- **Agents use the preview.** The reviewer agent opens the preview in a
991 browser, takes screenshots of what changed and attaches them to its
992 review, so an approver sees the result without reading the diff.
993- **Environments.** Preview, production and their secrets; deploy history
994 and one-click rollback.
995- **Scale to zero.** An idle branch costs neither g1t nor the customer
996 anything: a Worker runs, and is billed, only while it answers a request.
997 A preview is deleted when its pull request closes or merges, and after
998 a set number of idle days. Container apps, later, sleep when idle.
Plan: deployments are billed to the customer, never free999- **Billed to the customer, never free.** The user (2026-10-04): "we
1000 should not be giving any of this available for free". Every deployment
1001 is metered per workspace (requests, CPU time, deployed apps, stored
1002 data), priced at Cloudflare's cost + 20% like agent usage, and drawn
1003 from prepaid credit. `FREE_WHILE_BUILDING` and the free model allowance
1004 do not cover deployments: a workspace without credit cannot deploy, and
1005 turning deployments on says so first.
Plan: turning deployments on is a paid monthly plan1006- **Turning them on is a paid plan, the way Cloudflare's is.** "Including
1007 things like them even enabling the feature should have that pay like
1008 Cloudflare does." Enabling deployments for a workspace starts a monthly
1009 fee that includes an allowance of requests, CPU time and deployed apps;
1010 usage past it is billed per unit, as Workers for Platforms bills g1t.
1011 The fee and allowance are the user's to set.
1012- **Recommended, off in one click.** Because enabling costs money, it is
1013 never switched on without the workspace agreeing: new repositories
1014 recommend it prominently. A repository can turn it off, keep only production, or
Plan: a repository that maintains itself, and deployments on g1t.page1015 deploy somewhere else from its own workflows. Apps built for Cloudflare
1016 (Workers, static assets, D1, KV, R2) deploy without configuration.
1017
Merge branch 'worktree-agent-a3abfcce648e87dca'1018Later, toward GitLab's DevOps breadth: package and container registries,
1019releases, container hosting. (Environments' protection rules for g1t
1020Actions were built on 2026-10-08; see above.)
Plan: a repository that maintains itself, and deployments on g1t.page1021
Plan: Projects, the home of everything about running software1022## Projects
1023
1024> **2026-10-04:** the user: "an extra dimension of Projects so it's not
1025> just repositories … where a lot of things can live", "very Vercel
1026> like", with dependencies across projects "the Platform Engineering /
1027> Port route", and "the repository is *part* of a project: you could be
1028> mirroring it from GitHub/GitLab/Bitbucket, or you could let us host it
1029> for you", with room for Mercurial or anything else later.
1030
1031**A project is the thing you are building and running; a repository is
1032where some of its code lives.** Everything that is about running software
1033(deployments, environments, domains, secrets, dependencies, owners,
1034health, upkeep) belongs to the project. What is about the code itself
1035(branches, pull requests, review, merge rules) stays with the repository.
1036That split is what lets the code live anywhere.
1037
1038### The model
1039
1040| | What it is | Like |
1041| --- | --- | --- |
1042| **Workspace** | The company or team. Members, billing, plans, shared secrets. | Vercel team, GitLab group, GitHub org |
1043| **Group** | An optional named set of projects, one level: "Payments", "Mobile". For browsing, ownership and shared settings. | GitLab subgroup, Backstage system, Port domain |
1044| **Project** | One deployable thing: a site, an API, a worker, a library. Has exactly one **source**. | Vercel project, Port service, Backstage component |
1045| **Source** | Where its code is: a repository and a **root directory** in it. | Vercel's connected repo + root directory |
1046| **Dependency** | Project A uses project B: calls its API, consumes its package, reads its queue. | Port relations, Backstage `dependsOn` |
1047
1048- **One project, one source; one repository, any number of projects.** A
1049 project builds from exactly one place, which keeps it as simple as
1050 Vercel's. A monorepo is several projects on one repository, each with
1051 its own root directory (`apps/web`, `services/api`), and a push builds
1052 only the projects whose root it touched. The common case stays 1:1, and
1053 every existing repository gets a project of its own name when this
1054 ships, so nobody has to set anything up.
1055- **Groups are for people; dependencies are for software.** Groups decide
1056 where a project shows up and who owns it. Dependencies decide what
1057 happens when one changes. Neither replaces the other, and a dependency
1058 can cross groups.
1059
1060### Sources: where the code lives
1061
1062A source is an adapter behind one interface (`SourcePort`: clone URL,
1063branches, commits, pushes as events, pull requests if it has them):
1064
1065| Source | Code lives | g1t gets pushes by | Pull requests |
1066| --- | --- | --- | --- |
1067| **Hosted on g1t** (today) | Artifacts | its own events | g1t's, with agents, the queue, review |
1068| **Mirrored** from GitHub, GitLab or Bitbucket | Both; g1t keeps a copy | the provider's webhook, then fetch | The provider's, read into g1t; agents open theirs there |
1069| **Connected, not copied** | The provider only | webhook | The provider's |
1070| **Later:** Mercurial, Perforce, a tarball upload | Behind the same port | per adapter | per adapter |
1071
1072A mirrored or connected project still gets everything that is the
1073project's: previews on its pull requests (a status and a comment on
1074GitHub's), production on its default branch, secrets, dependencies,
1075upkeep agents. That is the on-ramp: a team keeps GitHub and gets g1t's
1076deployments and agents first, and moves the code later or never.
1077Bring-your-own-git is also why the project, not the repository, holds the
1078URL `g1t.sh/<workspace>/<project>`.
1079
1080### What lives on a project
1081
1082| | Today it is on | Moves to the project |
1083| --- | --- | --- |
1084| Deployments: production, previews, build settings, root directory, framework | The repository | Yes |
1085| Environments: production, preview, and custom ones (`staging`) with protection rules (required approvers, branch limits) | Nowhere yet | New, on the project |
1086| Domains: `<project>--<workspace>.g1t.page`, and custom domains | The repository's name | Yes |
1087| Secrets and variables | The repository | Yes. Workspace rows link to projects instead of repositories. A repository's workflows read the rows of its project (with several projects on one repository, the one marked as the repository's default). |
1088| Dependencies | Nowhere | New |
1089| Owners, on-call, links (docs, dashboards, runbooks) | Nowhere | New: the catalog's metadata |
1090| Health: scorecards (has an owner, CI passes, dependencies current, no open security alerts, deploys within N days) | Nowhere | New |
1091| Upkeep agents: dependency updates, security alerts | The plan | Scoped per project |
1092| Logs and analytics of the running app | Nowhere | New: requests, errors and CPU per environment, from Workers analytics |
1093| Branches, pull requests, review, merge rules, the queue, webhooks | The repository | Stay |
1094
1095### Dependencies: why this gets powerful
1096
1097Declared in the UI, or in the source as `.g1t/project.yml` (which wins
1098when present, as `catalog-info.yaml` does in Backstage):
1099
1100```yaml
1101name: web
1102root: apps/web
1103dependsOn:
1104 - project: api # calls its HTTP API
1105 as: API_URL # its URL, per environment, as a variable
1106 - project: ui-kit # consumes its package
1107```
1108
1109What g1t does with them:
1110
11111. **Reference variables.** `API_URL` above resolves to `api`'s production
1112 URL in production and to the matching preview in a preview, the way
1113 Railway's `${{ api.URL }}` references work. No hard-coded URLs.
11142. **Preview stacks.** A pull request on `api` gets its own preview, and
1115 **Preview with dependents** builds `web`'s preview pointed at it, so a
1116 reviewer clicks through the whole change across projects. A change that
1117 spans repositories (one issue, one fork per repository) gets one stack.
11183. **Release order.** Production deploys go out in dependency order; a
1119 change set across projects lands through the queue together or not at
1120 all.
11214. **Impact on every pull request.** "Changes `api`; `web` and `mobile`
1122 depend on it." Agents get the graph in their context: an agent
1123 changing an API opens follow-up issues on the projects that call it,
1124 and reviewers see what else could break.
11255. **Upkeep across the graph.** A vulnerable package in `ui-kit` opens
1126 issues, assigned to agents, on every project that consumes it.
11276. **Scorecards turn into work.** A project failing a scorecard check
1128 ("no owner", "dependencies 90 days old") gets an issue an agent can fix.
1129 That is the Port idea with the work done for you.
11307. **The map.** A workspace's projects as a graph, coloured by health and
1131 by what is deploying now.
1132
1133### Pages
1134
1135- `g1t.sh/<workspace>`: projects first (grouped, with health and
1136 production status), then repositories.
1137- `g1t.sh/<workspace>/<project>`: overview (production, latest previews,
1138 health, owners, dependencies both ways), **Deployments**,
1139 **Environments**, **Secrets and variables**, **Logs**, **Settings**
1140 (source, root directory, build, domains, groups, owners).
1141- A hosted repository keeps its code pages; from a project they are its
1142 **Code** tab. A repository page lists the projects built from it.
1143
1144### Services
1145
1146- `services/projects` (new): projects, groups, sources, dependencies,
1147 owners, scorecards. Events `project.created`, `project.updated`,
1148 `dependency.changed`.
1149- `services/deployments`: keyed by project instead of repository.
1150- Secrets and variables: the scope becomes workspace → project.
1151- Sources: the hosted adapter wraps `services/repos`; a mirror adapter
1152 per provider in `services/integrations`, which already holds those
1153 connections.
1154
1155### Build order
1156
11571. **Projects as the home of deployments and secrets**, 1:1 with every
1158 existing repository: the service, the pages, deployments and secrets
1159 moved to the project, `<project>--<workspace>.g1t.page`.
11602. **Dependencies:** declared in the UI and `.g1t/project.yml`, reference
1161 variables, impact on pull requests and in agents' context, the map.
11623. **Preview stacks** and cross-project change sets.
11634. **Monorepos:** several projects on one repository, each with a root
1164 directory, building only what a push touched.
11655. **Mirrored sources:** GitHub first, then GitLab and Bitbucket.
11666. **Groups, owners, scorecards** feeding the upkeep agents.
11677. **Environments** with protection rules; custom domains; logs.
1168
Projects: what a workspace builds and runs, first on every page1169**Step 1 shipped 2026-10-04:** `services/projects`; every repository a
1170project of its own name; the site projects-first (workspace page of
1171project cards, the project overview at `g1t.sh/<workspace>/<project>`, code
1172under `/code`, the sidebar and the New project flow); deployments keyed by
1173project and branch at `<project>-<workspace>.g1t.page` and
1174`<project>-git-<branch>-<workspace>.g1t.page`; secrets and variables owned
1175by the project.
1176
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1177**Step 5, GitHub, built 2026-10-05:** one GitHub App (`g1t-sh`) for both
1178sign-in and repository access. Sign-in is its user authorization with PKCE
1179(identity, `src/github.rs`): accounts known by GitHub's numeric id, a
1180matching verified email never linked without signing in to the account,
1181new accounts behind the invite check. Repositories come through its
1182installations (integrations, `src/github.rs`), copied with every branch and
1183tag by the repos service (`src/mirror.rs`) as **import**, **mirror** (g1t
1184follows GitHub on its push webhook) or **move to g1t** (GitHub follows g1t
1185on `git.push`). A mirror is a hosted repository that keeps a full copy, so
1186its project stays `hosted` and deploys like any other; the tie lives in
1187integrations' `github_repos`. Not yet: previews and statuses on GitHub's own
1188pull requests, comments and pull requests copied, GitLab and Bitbucket.
1189
Projects: what a workspace builds and runs, first on every page1190### People and search
1191
1192> **2026-10-04:** "pull up user profiles, using a /u/username prefix kinda
1193> like DockerHub … search for users if you search that explicitly, how
1194> GitHub has the aside for searching against filters … a significantly
1195> stronger implementation."
1196
1197- **Profiles at `g1t.sh/u/<username>`**, apart from workspaces at
1198 `g1t.sh/<workspace>`: who they are, their workspaces, recent work,
1199 agents' sessions they steered.
1200- **Search with a filter sidebar:** Projects, Code, Issues, Pull requests,
1201 Users, Workspaces, each with its count; filters by workspace, language,
1202 state, author, agent, label, date; qualifiers in the query
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent1203 (`user:`, `is:open`, `agent:g1t`) as on GitHub. Typing `u/name`
Projects: what a workspace builds and runs, first on every page1204 searches people directly, as Docker Hub does.
1205
Plan: Projects, the home of everything about running software12061 and 2 serve the competition directly (multi-agent coordination across
1207projects is 25% of the score); 3 is the demo's best moment if time allows.
1208
Plan: the billing model1209## Billing model
1210
1211> **2026-10-04:** "Some things just require you to have a card on file …
1212> some things will be something you give us an initial amount of money
1213> per month just to activate, tons of things additionally will be usage
1214> based, some things will just be usage based only … at minimum a
1215> breakeven with Cloudflare costs, or in some cases a value add." Stripe
1216> moves to Flagon, Inc. (g1t.sh is its product). Proposed below; the
1217> prices are the user's to confirm.
1218
1219### Four kinds of charge
1220
1221Every feature is exactly one of these, and the Billing page says which:
1222
1223| Kind | What the workspace does | Example |
1224| --- | --- | --- |
1225| **Free** | Nothing | Hosting code, issues, pull requests, review, the merge queue, bringing your own agent over MCP |
Prices are what g1t pays plus 20%, from the first second1226| **Card on file** | Adds a card; pays only for what it uses | Previews, g1t's agents, workflow minutes |
Plan: the billing model1227| **Activation** | Turns a feature on for a monthly fee that includes an allowance; usage past it is metered | Production deployments, Security and quality |
1228| **Usage only** | Nothing up front; every unit is metered | Model tokens, build minutes, storage past the free amount |
1229
1230A card is needed before anything that can cost money starts. Nothing is
1231ever switched on without the workspace choosing it.
1232
1233### Postpaid, with spend limits
1234
1235- **One Stripe customer and one subscription per workspace**, on Flagon,
1236 Inc.'s account. Activations are licensed line items; every usage
1237 dimension is a metered price backed by a Stripe Meter. Stripe invoices
1238 monthly in arrears and charges the card on file; failed payments go
1239 through Stripe's retries and emails, and g1t hears of them by webhook.
1240- **Spend limits instead of prepaid credit.** A workspace sets a monthly
1241 limit overall and per feature (Vercel's spend management). g1t counts
1242 usage as it happens and stops starting new paid work at the limit,
1243 with a warning at 50%, 80% and 100%. Prepaid top-ups go away; promotions
1244 (the free model allowance) become Stripe credit on the customer.
1245- **Usage reaches Stripe from billing alone.** Every service reports
1246 usage to the billing service as it happens (it already records agent
1247 runs and builds); billing batches them into Stripe meter events every
1248 few minutes, idempotently by g1t's own ids, and keeps the ledger g1t's
1249 pages show. Nothing else talks to Stripe.
1250
1251### Scope: workspace, then projects
1252
1253- A feature is turned on for the **workspace** (by an owner, with the
1254 activation if it has one), then allowed for **all projects** or
1255 **selected projects**.
1256- Every **project** can opt out on its own page. A project with nothing
1257 to deploy (no Workers config, no build script, no `index.html`) is
1258 detected, says so on its Deployments page, and never builds or costs
1259 anything.
1260- Agents and workflows are allowed per project the same way, so a
1261 workspace can keep spend to the projects that matter.
1262
Plan: prices pass every Cloudflare cost through1263### Prices: what it costs us, passed through
1264
1265> **2026-10-04, decided:** postpaid with spend limits, as Vercel and
1266> Cloudflare do; no per-seat price, ever ("fuck per-seat pricing").
1267> "If they're barely using them great, but if they're using the shit out
1268> of them that will cost me a ton, so that cost needs to move onto them."
1269
1270**Every Cloudflare cost a workspace causes is metered to it.** Light use
1271fits in a small free allowance; past it, each unit is charged at
1272Cloudflare's price times a margin of at least 1.5, which pays for Stripe
1273(about 3%), shared overhead (the site, the API, D1) and g1t itself.
Plan: the billing model1274
Plan: prices pass every Cloudflare cost through1275Cloudflare's prices (October 2026), and the cost per unit g1t meters:
Plan: the billing model1276
Plan: prices pass every Cloudflare cost through1277| What g1t meters | Cloudflare's price | Cost to g1t per unit |
1278| --- | --- | --- |
1279| **Sandbox minute** (agents, checks, merge queue, workflow jobs, deploy builds), standard-1: ½ vCPU, 4 GiB, 8 GB | CPU $0.00002 / vCPU-s while busy; memory $0.0000025 / GiB-s and disk $0.00000007 / GB-s while running | ≤ $0.0012 / minute (CPU counted as busy throughout, since g1t cannot see it per sandbox) |
1280| **App request** (deployments) | Workers for Platforms: $0.30 / million past 20M | $0.30 / million |
1281| **App CPU** | $0.02 / million CPU-ms past 60M | $0.02 / million ms |
1282| **App** (a deployed script) | $0.02 / script-month past 1,000 | $0.02 / app-month |
1283| **Storage** (repositories, artifacts, caches) | Artifacts $0.50 / GB-month (billing starts 2026-10-14); KV $0.50 / GB-month | $0.50 / GB-month |
1284| **Git operation** (clone, fetch, push) | Artifacts $0.15 / 1,000 past 10,000 | $0.15 / 1,000 |
1285| **Model tokens** | The provider's price | As charged |
1286| Container egress, emails, the site's own requests | Small and shared | In the margin |
1287
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas1288> **2026-10-06, decided:** no per-feature quotas on the plan. "A paying
1289> user should be able to push past the Git operations number, they're
1290> just paying usage on it." One plan, $20 a month per workspace with $10
1291> of usage included; every meter is charged from the first unit at cost +
1292> 20% (builds, app requests and CPU, custom domains), drawn from the $10
1293> first, then up to the spend limit, which is the only thing that stops a
1294> paying workspace (with abuse protection). Projects, previews and apps
1295> are not metered (Workers for Platforms' script pool makes them ~free).
1296> The forge's free amounts are the same for everyone: 1 GB private storage
1297> and 50,000 git operations a month; past them the plan pays and a free
1298> workspace is held (pushes stop, git slowed). The table below is the
1299> earlier proposal; billing's price book and g1t.sh/pricing are current.
1300
Plan: prices pass every Cloudflare cost through1301What a workspace pays:
1302
1303| Meter | Free each month | Then | Margin | For comparison |
1304| --- | --- | --- | --- | --- |
Prices are what g1t pays plus 20%, from the first second1305| Sandbox minutes | None (2026-10-05: charged from the first second) | Cost + 20%, by the second | 1.2× | GitHub Actions $0.008 / minute (Linux 2-core); Vercel builds $0.0035 / CPU-minute |
Plan: prices pass every Cloudflare cost through1306| App requests | 1 million with Deployments | $0.50 / million | 1.7× | Vercel $0.60 / million invocations |
1307| App CPU | 3 million ms with Deployments | $0.04 / million ms | 2× | Vercel active CPU about $0.036 / million ms |
1308| Apps | 10 with Deployments | $0.05 / app-month | 2.5× | |
1309| Storage | 1 GB | $1.00 / GB-month | 2× | GitHub LFS $0.07 / GB, but repositories are free there |
1310| Git operations | 10,000 | $0.30 / 1,000 | 2× | |
1311| g1t's models | | Cost + 20% | 1.2× | The provider's own price |
Prices are what g1t pays plus 20%, from the first second1312| Your own model provider | | Only its sandbox minutes (the $0.10 run fee was dropped 2026-10-05) | | |
Plan: prices pass every Cloudflare cost through1313| **Deployments** activation | | $5 / month, with the allowances above | covers Workers for Platforms' $25 / month across workspaces | Vercel Pro $20 per seat |
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1314| **Security and quality** activation (built 2026-10-07: price book meter `security_activation`) | | $10 / month; fixes as agent usage | | GitHub Advanced Security $49 per committer |
Plan: the billing model1315
Plan: prices pass every Cloudflare cost through1316A workspace that uses g1t lightly (a few agent runs, a small site)
1317pays nothing or its activation; a workspace running agents all day pays
1318for the sandboxes and models those agents use, with g1t's margin on
1319each. Nothing in a workspace's bill is subsidised by another's.
Plan: the billing model1320
1321### Build order
1322
13231. Stripe customer per workspace and card on file (Checkout in setup
1324 mode), webhooks (invoice paid and failed, subscription changes,
1325 payment method changes), the Billing page rebuilt around the four
1326 kinds.
13272. One subscription per workspace with activations as items; Deployments
1328 moves onto it.
Plan: prices pass every Cloudflare cost through13293. Meters for each usage dimension above, fed from billing's ledger:
1330 every sandbox reports how long it ran when it stops (agents, checks,
1331 the queue, workflow jobs and deploy builds alike); deployments report
1332 requests, CPU and apps; repos report storage and git operations. Spend
Plan: the billing model1333 limits and their warnings; prepaid credit retired.
13344. Per-workspace allow-lists of projects for each feature, and per-project
1335 opt-out; "nothing to deploy" detection.
Billing accounts, terms and enterprises; g1t is no longer free13365. Turn off FREE_WHILE_BUILDING when the user says so. **Done 2026-10-05.**
1337
1338Shipped by 2026-10-05: sandbox seconds for every sandbox; the price book
1339and its keeper (runs settled to AI Gateway's price every 15 minutes;
1340Container and Workers costs checked against Cloudflare's billable usage
1341and container analytics daily, with a public change log on
1342g1t.sh/pricing); usage limits by trust with automatic payment near the
1343limit; app traffic counted toward limits as it happens; billing accounts,
1344terms and enterprises; free mode off, syntaqx comped.
1345
1346Still to build, in order: Stripe card-on-file without a payment (setup
1347mode) and webhooks; month-end invoices for postpaid usage (and one
1348invoice per enterprise); the subscription with activations as items;
1349storage and git-operation meters; limit warnings by email at 50/80/100%;
1350self-serve enterprise management for enterprise owners.
1351
1352### Accounts, terms and enterprises
1353
1354Every workspace is paid for by a billing account: its own (`ws_<slug>`)
1355or an enterprise's (`ent_…`), which pays for several workspaces with one
1356limit, one set of terms and, once invoices exist, one bill, as GitHub
1357Enterprise does. Terms are standard, comped (nothing charged, usage still
1358recorded at cost, paid features on) or custom (a discount, its own
1359ceiling, an end date). g1t staff manage them in **sudo.g1t.sh**, a
1360separate Worker behind Cloudflare Access that also verifies the Access
1361token itself and allows only listed staff emails; every change is kept
1362with who made it and why.
1363
1364### Limits: stop non-payers, never payers
1365
1366The limit is on usage not yet paid for, counted at cost to g1t or charge,
1367whichever is more: $3 before any live payment, then twice what has been
1368paid ($25 to $1,000), or what staff set. A workspace with a card on file
1369is charged automatically near its limit, which both pays what it owes and
1370raises the limit, so paying users are never stopped. A declined card
1371stops work until paid. The owner's own spend limit always means stop.
1372Test-mode payments never lower exposure or raise trust.
Plan: the billing model1373
Merge Stripe Tax, the card fee on card payments, and one free workspace per person1374### Tax, card fees and free workspaces (built 2026-10-08)
1375
1376> **2026-10-08, decided:** Stripe Tax everywhere ("so I don't fuck up on
1377> taxes"); Stripe's card fee passed to the customer with the 20% markup
1378> kept; one free workspace per person; no invites on free workspaces.
1379
1380- **Stripe Tax on every payment.** `automatic_tax` on every Checkout page
1381 (plan, Security and quality, prepaying, AI credit), every subscription
1382 and every invoice g1t makes (month close, threshold, enterprise), and a
1383 tax calculation and transaction for auto-reload's off-session charge.
1384 Tax code `txcd_10103001` (SaaS, business use), every price
1385 `tax_behavior=exclusive`. Checkout always collects the billing address
1386 and tax ID and saves them on the customer. Prices on g1t are shown
1387 excluding tax. Tax is never revenue: balances and plan payments are
1388 credited without it, it is kept in `tax_and_fees`, shown as its own
1389 statement line, and as **Tax collected** on sudo's Costs. Without an
1390 address g1t does not charge: the owners are asked for one.
1391- **The card fee** (2.9% + $0.30, grossed up) is its own line on every
1392 card payment, the plan's and Security's as a monthly item; never on a
1393 bank transfer or an enterprise's invoice. On by default
1394 (`cost_settings.card_fee`). Not revenue either. Meters stay at cost +
1395 20%; models at the provider's price plus the agent rate.
1396- **One free workspace per person.** Identity asks billing
1397 (`free_workspaces`) before creating one; a second is refused with the
1398 way forward. Those who own several from before keep them.
1399- **A free workspace adds no one**: no members, invites or outside
1400 collaborators until it starts the plan; its members stay; @g1t never
1401 counts. Enforced in identity for every path (site, API, MCP).
1402- Details: docs/BILLING_OPERATIONS.md, *Tax and the card fee*.
1403
Billing: credits with a kind and expiry, discounts instead of comped, and safer charging1404### Promo codes (planned)
1405
1406Staff credits (promotional, goodwill, refund; `services/billing/src/grants.rs`,
1407docs/BILLING_OPERATIONS.md) are given one workspace at a time. Promo codes
1408give promotional credit in bulk, on redemption, through the same grants:
1409
1410- **Codes.** sudo → Credits & refunds → **New code**: the code (or one
1411 made up), the credit ($ amount), max redemptions, when the code stops
1412 working, how long each redeemed credit lasts (an expiry, as any grant),
1413 and a note. Table `promo_codes` (code, amount, max, redeemed, ends_at,
1414 credit_days, note, created_by, disabled_at) and `promo_redemptions`
1415 (code, workspace, grant id, by, at), unique on (code, workspace).
1416- **Redeeming.** An owner types it on the workspace's Billing page
1417 (`redeem_code`, owners only). One D1 batch checks the code is open, under
1418 its max and not redeemed by the workspace, counts the redemption and
1419 makes the grant (`grant_credit`, kind promotional, the code as its note),
1420 so two redemptions at once never pass the max. Wrong or used-up codes say
1421 so without telling which codes exist; redemptions are rate-limited per
1422 owner.
1423- **Seeing them.** Each code's redemptions, credit given and spent come
1424 from the grants it made, so margin needs nothing new: spent promo credit
1425 is already given away, by kind.
1426- **Not yet built** because it adds an owner-facing form, abuse limits and
1427 a second sudo form; giving credit by workspace covers launch.
1428
Workspaces own repositories1429## Agents and models
1430
1431### Defining an agent
1432
1433An agent is a file (`.g1t/agents/<name>.md`, or in the workspace library):
1434instructions, the harness and model to run, the tools and MCP servers it may
1435use, its sandbox image, permissions and budget. Agents take roles: planner,
1436implementer, reviewer, conflict resolver, documenter, memory consolidator.
1437Each role has a default that a repo can replace.
1438
1439### Where it runs, and on whose model
1440
1441| Option | How it works | Fits |
1442| --- | --- | --- |
1443| Hosted, g1t's model | g1t runs the sandbox and bills usage | Getting started; no keys to manage |
1444| Hosted, your API key | Same sandbox, your Anthropic, OpenAI or Google key | Teams with existing contracts |
1445| Hosted, your endpoint | Any OpenAI-compatible URL: Bedrock, Vertex, Azure, a self-hosted model | Private or fine-tuned models |
Issues and pull requests replace intents and attempts1446| Your runner | A g1t runner daemon on your own machines picks up pull requests | Code or models that may not leave your network |
Workspaces own repositories1447| Your own session | Local Claude Code, Cursor or any MCP client joins through `mcp.g1t.sh` | Individuals; subscription plans |
1448
1449Decisions behind this:
1450
1451- **g1t does not build its own agent loop.** It runs existing harnesses
1452 (Claude Code first, through its headless mode) behind a small runner
1453 contract: a container image, an entry command, and session events reported
1454 through the CLI. Other harnesses plug in by meeting the contract.
1455- **All hosted model traffic goes through Cloudflare AI Gateway.** That gives
1456 one place for spend tracking, budgets, rate limits, fallback and logs,
1457 whichever provider or endpoint is behind it.
Merge branch 'model-routing'1458- **Nobody has to pick a model.** A person assigns work to `g1t`, as
1459 they would assign an issue to a colleague, and **Auto** routes each job
1460 to the cheapest model that can do it (see
1461 [Routing for cost](#routing-for-cost) below). A workspace can pin a tier
1462 per kind of work instead. Each request is tagged at the gateway with the
1463 kind of work, the tier, the repository and the pull request, and each
1464 run says which model ran and why. The gateway's own dynamic routes
1465 cannot make the choice yet: they work only on its OpenAI-compatible
1466 endpoint, and the harness speaks Anthropic's.
Workspaces own repositories1467- **Subscriptions stay local.** A Claude subscription cannot be used by a
1468 hosted sandbox; it needs an API key. People on subscriptions use their own
1469 Claude Code session, which is a full participant.
Merge branch 'model-routing'1470- **The workspace pays.** A workspace buys AI credit by card and each
1471 agent run deducts the model at the provider's price plus the agent rate
1472 per million (weighted) tokens; on its own model key, only the agent rate,
1473 counted from the model proxy and the sandbox's own report. The billing service asks
Agents as a team: lifecycle, merge queue, billing and a new shell1474 nothing of the others: the runner asks it before starting a sandbox and
1475 is refused when there is no credit, and the sandbox reports what its run
1476 cost with a token only it holds. Where no card processor is configured
1477 nothing is charged and agents stay limited to listed accounts.
Workspaces own repositories1478- **Keys are secrets.** Stored in Cloudflare Secrets Store, injected into the
Issues and pull requests replace intents and attempts1479 sandbox for one pull request, never shown again.
Workspaces own repositories1480
Agents as a team: lifecycle, merge queue, billing and a new shell1481### Seeing a pull request through
1482
1483Assigning an issue is the only thing a person does until there is something
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent1484to merge. A pull request made by g1t goes through checks, a review
Agents as a team: lifecycle, merge queue, billing and a new shell1485by another agent, revision when either finds something, and catching up
1486when `main` moves, without anyone pressing a button. It ends as ready to
1487merge, or as "needs you" with the reason: the checks still fail after two
1488revisions, a review could not be written, or a conflict could not be
1489resolved.
1490
1491The work service decides the next step from the pull request's state and
1492claims it in one statement, so a step is taken once. The runner asks on
1493every event that could change the answer (ready, pushed, checks finished,
1494review finished, `main` moved), and on a five-minute sweep for anything
1495missed, and carries the step out in a sandbox.
1496
1497A pull request does not have to be up to date with `main` to merge,
1498unless the repository's settings require it, as on GitHub. Merging one that
1499is behind brings it up to date first (a clean merge needs no model; an
1500agent resolves a conflict) and lands it when that push arrives. With the
1501requirement on, catching up is a step of its own and the checks run again
1502on the result.
1503
1504Each repository sets its own rules, on one settings page: whether its
1505default branch takes pushes at all, how many approvals a merge needs and
1506whether an agent's counts, whether failed checks can be overridden, whether
1507a second agent reviews, and how often an agent is sent back before a person
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent1508is asked. A pull request g1t opens follows the same rules as anyone's.
Agents as a team: lifecycle, merge queue, billing and a new shell1509Pushes to a protected branch are refused in the git front end, with the
1510reason shown by git beside the branch.
1511
1512Merging is a person's decision unless the repository says otherwise. With
1513"merge automatically when ready" turned on in its settings, a ready pull
1514request lands by itself, attributed to `g1t`. That is the whole path from
1515an assigned issue to a commit on `main` with nobody in between. Required
1516human approval per path, and risk tiers, are still to come.
1517
Merge branch 'model-routing'1518### Routing for cost
1519
1520*Built (runner `route` in `services/runner/src/model-env.ts`).* The goal
1521is cost per merged change, not cost per request: a cheap attempt that
1522fails and is retried on the same model costs more than one that finishes.
1523
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb971524- **Tiers and catalogue.** `small` (Claude Haiku 5.5 since 2026-10-08,
1525 $0.10/$0.50 per million input/output up to 100k-token prompts, five
1526 times that above; it was Haiku 4.5 at $1/$5), `large` (Claude Sonnet 5.5, $2/$10) and `frontier`
Merge branch 'main' into actions-toolkit-oidc-artifacts1527 (Claude Opus 5.5, $4/$20). Models, names and list prices are data,
1528 never code: since 2026-10-08 billing's model catalogue
1529 (`gateway_models`, one row per model g1t can use) and staff's defaults
1530 in sudo, **Agents & models** (`model_defaults`: each tier's model, the
1531 harness's background model, the AI Gateway's first Claude, each job's
1532 starting tier and effort), read by the runner once a minute over
1533 `AGENT_ROUTING`, which is only the fallback when billing cannot be read.
1534 Catalogue prices are for estimates only; runs are charged what AI
1535 Gateway priced them at.
1536- **Keeping up with new models (built 2026-10-08).** The models service
1537 lists Anthropic's models (through the AI Gateway) and Workers AI's daily
1538 and on demand; a new id lands in the catalogue as `new`, priced from a
1539 maintained table of Anthropic's list prices or Workers AI's listing, or
1540 unpriced, and staff are emailed. Nothing routes to it, offers it or
1541 charges for it until staff approve it with its prices. A model a provider
1542 stops listing is `deprecated`; routing never sends work to a deprecated
1543 or retired model, falling back to the next model of the tier and saying
1544 so on the run. Customers keep Auto: the catalogue is staff's. See
1545 [BILLING_OPERATIONS.md](BILLING_OPERATIONS.md#the-model-catalogue).
Merge branch 'model-routing'1546- **Starting tier by job.** Catch-up, answering a question, and reviews of
1547 at most 10 files and 200 lines touching no sensitive path: small.
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb971548 Plans: small at high effort (Haiku 5.5 takes an effort level).
1549 Changes, revisions and other reviews: large. Reviews over 60 files
Merge branch 'model-routing'1550 or 3,000 lines: frontier. Labels: `architecture` frontier, `security` off
1551 small, `docs`/`documentation`/`typo` let changes and answers start small.
1552- **Escalation.** A failed (or guardrail-stopped) attempt at the same work
1553 goes one tier up; two in a row, frontier; a revision counts its rounds;
1554 a change left at low confidence sends the next attempt up.
1555- **Learning, per repository.** From the last 20 runs of the same kind:
1556 one tier down when the cheaper tier finished at least 90% of at least 5
1557 (never for sensitive or labelled work, never on a retry); one tier up
1558 when this tier failed at least half of at least 5. No new tables: it
1559 reads work's `agent_runs` (model, status, confidence).
1560- **Explained.** Every run's first step and session note is one line:
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb971561 *Used a fast model (Claude Haiku 5.5): small change, 3 files and 80
1562 lines.* Effort per kind of job (`effort` in `AGENT_ROUTING`: plan high,
1563 answer medium, update low) is sent as `CLAUDE_CODE_EFFORT_LEVEL` on
Merge branch 'main' into actions-toolkit-oidc-artifacts1564 g1t's tiers (never on a model the catalogue says takes none) and named
1565 in that line, with the catalogue's name for the model.
Merge branch 'model-routing'1566- **Chosen instead.** `model_routes` rows to g1t's models name `small`,
1567 `large` or `frontier`, or nothing for Auto (Integrations → Models).
1568 A workspace's own Anthropic key with no model named is routed by Auto
1569 too.
1570- **Measured.** `scripts/ops/routing-savings.mjs` replays tasks through
1571 the router offline, priced from the catalogue, against routing before
1572 Auto and against the frontier model for everything, net of failed
1573 attempts, with cost per merged change; `--live` reads billing's runs and
1574 counted tokens. On the bundled sample (13 tasks, assumed failures): Auto
1575 costs 7% less than the frontier model for everything and about 7% more
1576 per run than routing before it, but half as much per merged change,
1577 because it finishes the hard tasks the old routing gave up on. At
1578 current prices Opus 5.5 and Sonnet 5.5 cost the same per cache read, and
1579 cache reads are most of an agent run's tokens, so moving off the
1580 frontier model saves less than its list price suggests; the fast tier
1581 and fewer failed attempts are where the money is. Run `--live` monthly
1582 and after any routing change.
1583- **A cheaper route for the simplest jobs (designed, off).** A fourth tier
1584 on Workers AI through AI Gateway (an open model, billed on Cloudflare's
1585 invoice) for classification-sized jobs: commit messages, triage,
1586 summaries. Behind the same router as a tier with its own catalogue entry
1587 and `tasks` rules, off by default. It needs the proxy to translate the
1588 harness's Anthropic requests to the gateway's OpenAI-compatible
1589 endpoint (it already does for workspaces' own OpenAI-shaped providers)
1590 and a quality bar from the savings harness before any job moves to it.
1591
Workspaces own repositories1592### Choosing the right agent automatically
1593
Issues and pull requests replace intents and attempts1594Because several agents can work on the same issue, every issue with more
1595than one pull request is an evaluation on real work. g1t records, per repo and per kind of issue, each
Workspaces own repositories1596agent's win rate, cost and time. That produces a leaderboard, and a routing
Issues and pull requests replace intents and attempts1597policy: send each new issue to the agent that wins that kind most often,
Workspaces own repositories1598start with the cheapest that is good enough, and escalate to a stronger one
1599when checks fail.
1600
Plan: the inbox, then channels and apps, instead of discussions1601## Talking: the inbox and channels
1602
1603Not a discussions forum. People and agents need one place to talk in real
1604time, and an app that feels like one on desktop and phone.
1605
1606**The inbox comes first.** Everything that needs a person or that they
1607follow, from people and agents: review requests, agent questions and
1608handoffs, failures, mentions, deploys. Read and unread, saved, done,
1609snoozed; ranked so what an agent is blocked on comes first; email digests
1610and push. It is the delivery layer chat needs too (who is told what, read
1611state, push), so building it first makes channels cheap.
1612
Docs: inbox threads, reasons, subscriptions, watching, email, API and MCP1613*Built:* the events service keeps it (`services/events/src/inbox.rs` and
1614`subscriptions.rs`, migrations `0005_inbox` and `0006_inbox_threads` on the
1615`g1t-events` database), writing items as events arrive from the bus; work's
1616`inbox_subject` says what each event names. Each person has one **thread**
1617per issue, pull request, workflow on a branch or deployment: new activity
1618brings it back unread with a count and its last 10 activities, and while it
1619is unread its most urgent severity is kept. Each item has a **reason**
1620(`agent`, `review_requested`, `assign`, `mention`, `ci_activity`,
1621`security_alert`, `state_change`, `author`, `comment`, `manual`,
1622`subscribed`). Who is told: `agent.asked` and `pull.stalled` (needs you,
1623closed again by `pull.resumed` and the like), `pull.review_requested`
1624(needs you, closed by `pull.review_request_removed`),
1625`issue.assigned`/`pull.assigned`, failed checks and workflows,
1626`deployment.failed` and a recovering `deployment.succeeded`, g1t's reviews
1627and finished changes, closes, reopens and merges to everyone subscribed,
1628and comments to the people mentioned and everyone subscribed. Never the
1629actor, never g1t. **Subscriptions**: authors, assignees and reviewers are
1630subscribed without a row; commenting or being mentioned subscribes; anyone
1631can subscribe, unsubscribe (still told of what is asked of them) or ignore.
1632**Watching** a repository: participating (the default), all, ignore, or
1633custom (issues, pulls, deployments, security); whoever creates a repository
1634watches it at their default, all activity unless they change it.
1635**Settings**: which reasons are also emailed (agent, review_requested and
1636mention by default) and the default watch for new repositories; email goes
1637through identity's `notify_by_email`, to a confirmed address only while the
1638person can still read the repository. **REST and MCP**: 14 operations under
1639`/notifications`, `/repos/:owner/:name/subscription` and
1640`/user/subscriptions` (scopes `notifications:read` and
1641`notifications:write`, in the Agent preset), and the `notifications` MCP
1642tool; never usable by g1t's own tokens. On the site: a bell in the top bar
1643opening a sheet with tabs (All, Needs you, Errors, Success, Info), Done,
1644Save, Snooze and Mark all read; `/inbox` with Saved, Done and a reason
1645filter; reasons and update counts on each card; a Notifications box on
1646issue and pull request pages; a Watch menu in the repository header;
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar1647Settings → Notifications; a Needs you card on mission control. Agent sits
Docs: inbox threads, reasons, subscriptions, watching, email, API and MCP1648beside the bell, disabled. Still to come: security alerts (the security
Previews build from any branch; Agent in place of Ask AI; pin from the sidebar1649service publishes no event yet), email digests and push, Agent, and
Docs: inbox threads, reasons, subscriptions, watching, email, API and MCP1650channels.
Docs: the inbox, what lands in it and why, its tabs and actions1651
Plan: the inbox, then channels and apps, instead of discussions1652**Channels** (working name): workspace channels, direct messages and
1653threads, live.
1654
1655- Each channel is a Durable Object holding its WebSocket connections with
1656 hibernation, so idle channels cost nothing; history in D1, files in R2.
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent1657- Agents are members. `@g1t` in a channel starts work, answers, or
Plan: the inbox, then channels and apps, instead of discussions1658 posts a summary; agents post their questions and handoffs where people
1659 already are. A thread becomes an issue or an outcome in one action, and
1660 the agent's progress streams into that thread.
1661- Tied to the work: issues, pull requests, runs and deploys each have a
1662 thread; links unfurl into live cards (checks, agent step, preview).
1663 What a channel settles can become workspace memory, with its source.
1664- Apps: an installable PWA first (desktop and mobile, offline shell, Web
1665 Push), then native shells on the same API: Tauri for desktop (tray,
1666 deep links), React Native for iOS and Android (background
1667 notifications).
1668
1669GitHub-style Discussions are not planned: channels and threads on the
1670work replace them.
1671
Workspaces own repositories1672## What GitHub ships today, and where g1t differs
1673
1674GitHub's Agent HQ and Copilot app give each agent session its own git
1675worktree and branch, list sessions in a mission-control view grouped by
1676project, and let a task be assigned to several agents so their output can be
1677compared. Underneath, the unit of work is still a branch and a pull request.
1678
1679| | GitHub | g1t |
1680| --- | --- | --- |
1681| Where a session works | A worktree on one developer's machine, or a cloud sandbox | A server-side fork that any agent on any machine can join and anyone can open |
1682| Agent context | Lives in the app's session view | Stored with the repository and linked from each commit (why-blame) |
Issues and pull requests replace intents and attempts1683| Several agents on one task | Separate pull requests to compare by hand | One issue holding every pull request made for it, compared side by side, with the merged one recorded on the issue |
Workspaces own repositories1684| Collisions between agents | Found as merge conflicts at the end | Flagged during the work (overlap radar) |
Issues and pull requests replace intents and attempts1685| Landing changes | One pull request at a time | A merge queue that lands the chosen one and closes the rest as superseded |
Workspaces own repositories1686| Which agents | Those offered through a Copilot subscription | Any MCP client, plus hosted agents |
1687
1688## How agents connect
1689
16901. **Bring your own agent.** A remote MCP server at `mcp.g1t.sh` lets Claude
Issues and pull requests replace intents and attempts1691 Code (or any MCP client) list issues, claim one, get a clone URL and
Workspaces own repositories1692 token, report progress and submit. Adding it is one command; sign-in is a
1693 browser OAuth flow with no token to paste. The `g1t` CLI installs Claude
1694 Code hooks that upload the session transcript as the agent works.
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent16952. **g1t's agent.** Assign an issue to g1t, or many issues at
Agents as a team: lifecycle, merge queue, billing and a new shell1696 once, each to an agent of its own. g1t starts a sandbox for each
1697 (Cloudflare Containers), running a coding agent headless against its
1698 own pull request and fork.
Workspaces own repositories16993. **API and CLI.** Everything above is available at `api.g1t.sh` and
1700 through `g1t`.
1701
1702## Public surfaces
1703
1704| Host | What it serves |
1705| --- | --- |
1706| `g1t.sh` | The site, git over HTTPS, git over SSH |
Agents as a team: lifecycle, merge queue, billing and a new shell1707| `api.g1t.sh` | REST API, with no version in its paths, with a published OpenAPI document, cursor pagination, rate-limit headers, idempotency keys on writes, server-sent events for live pull request state, and signed webhooks |
Workspaces own repositories1708| `mcp.g1t.sh` | Remote MCP server over streamable HTTP |
1709
1710g1t is its own OAuth 2.1 authorization server: authorization code with PKCE,
OAuth 2.1 sign-in for MCP clients and other applications1711dynamic client registration that stores nothing (a client id encodes its
1712own registration, so the open endpoint cannot be used to fill a database),
1713discovery metadata and rotating refresh tokens. Still to come: scopes
Issues and pull requests replace intents and attempts1714per resource (`repo:read`, `repo:write`, `issue:write`, `pull:write`).
Workspaces own repositories1715MCP clients, the CLI (device flow) and third-party apps all use it. Access
1716tokens and SSH keys remain for git itself.
1717
Merge branch 'worktree-agent-a8385d293d42c913a'1718### Workspace aliases (internal, built 2026-10-07)
1719
1720`g1t` is the product; `flagon-io` is Flagon, Inc., the organization that
1721builds it. So nobody mistakes one for the other, `g1t.sh/g1t` leads to
1722`g1t.sh/flagon-io`. That is a workspace alias: a name g1t's staff point at
1723a workspace, kept in identity's `workspace_aliases` (migration 0029, which
1724seeds `g1t`) by the workspace's id, so it follows renames. It is not a
1725customer feature and is not documented for users; staff add and remove
1726aliases on sudo's Aliases page, with a reason, in sudo's audit log. We may
1727give other companies one for a trading name the same way.
1728
1729An alias is resolved wherever an old slug is (identity's `resolve_slug`),
1730so it costs only the not-found path: site pages 301 to the same page under
1731the workspace, the API and MCP run the call again under its slug, package
1732registries 301, and git over HTTPS is answered in place
1733(`resolve_alias`), because pushes do not follow redirects. An alias is
1734never a route, a username or a workspace's slug, and nobody can register
1735it while it exists. `@g1t` stays g1t's agent: mentions link to how the
1736agent works, never to `/g1t`.
1737
Workspaces own repositories1738## Architecture
1739
1740| Component | Language | Runs on | Responsibility |
1741| --- | --- | --- | --- |
Issues and pull requests replace intents and attempts1742| `crates/contracts`, `packages/contracts` | Rust, TypeScript | — | The interface of every service, the event catalogue, shared types. Services and clients depend on this, never on each other's code. |
OAuth 2.1 sign-in for MCP clients and other applications1743| `services/identity` | Rust | Worker + D1 | Accounts, workspaces and memberships, sessions, SSH keys, access tokens, device sign-in, OAuth codes and grants |
Issues and pull requests replace intents and attempts1744| `services/repos` | Rust | Worker + D1 + Artifacts | Repository registry, contents, forks, diffs, landing, git over HTTPS. Storage sits behind a `GitStore` port with an Artifacts adapter. |
1745| `services/work` | Rust | Worker + D1 | Issues, pull requests, comments, sessions; later a Durable Object per repo for the landing queue and live state |
Agents as a team: lifecycle, merge queue, billing and a new shell1746| `services/billing` | Rust | Worker + D1 + Stripe | Each workspace's agent credit: payments, the ledger of every run, and the gate on starting one |
Events service in Rust, with RFC 3339 times and accurate push events1747| `services/events` | Rust | Worker + Queues + D1 | The event bus: durable log, and one queue per subscribing service |
g1t is one name: its agent's work, commits and comments show as @g1t, and nobody can claim g1t or g1t-agent1748| `services/runner`, `crates/runner` | TypeScript, Rust | Worker + Containers | Starts a sandbox per g1t run; the program inside runs the agent harness and reports through the public API |
Social cards for every page: og.g1t.sh1749| `services/og` | TypeScript | Worker + Cache API | Social cards at `og.g1t.sh`: one PNG per page of the site and the docs (satori and resvg), looked up as an anonymous visitor, so nothing private appears on one |
Workspaces own repositories1750| `apps/web` | TypeScript | Worker | Server-rendered site. Holds no data; calls services over RPC. |
Issues and pull requests replace intents and attempts1751| `apps/docs` | TypeScript | Worker (static) | Documentation and the API explorer |
API and MCP server in Rust; a public index at the API root1752| `apps/api` | Rust | Worker | REST API (`api.g1t.sh`), MCP server (`mcp.g1t.sh`) and OpenAPI document, all generated from one list of operations; the OAuth endpoints |
Workspaces own repositories1753| `crates/sshd` | Rust | Container | Git over SSH, bridged to Artifacts |
1754| `crates/merged` | Rust | Container | Trial merges, conflict matrix, landing merges (needs real git; the Artifacts binding is read-only) |
1755| `crates/core` | Rust | native and WASM | pkt-line, packfile and diff code shared by the above and by the Worker |
Issues and pull requests replace intents and attempts1756| `crates/g1t` | Rust | user's machine | CLI: auth, SSH proxy, Claude Code hooks, issues and pull requests |
Workspaces own repositories1757
Issues and pull requests replace intents and attempts1758Storage: Artifacts for repositories (one fork per pull request), D1 for accounts
Workspaces own repositories1759and metadata, R2 for session transcripts and logs, Durable Object SQLite for
1760per-repo coordination state.
1761
1762How the services fit together:
1763
1764- **Each service is its own Worker with its own database.** It deploys,
1765 scales and fails on its own. Callers reach it through a typed RPC binding
1766 to the interface in `packages/contracts`.
1767- **Expected failures are values.** Every call returns a `Result`, so "not
1768 found" or "forbidden" crosses a service boundary as data.
1769- **Side effects travel as events.** A service publishes what happened
Issues and pull requests replace intents and attempts1770 (`git.push`, `issue.opened`, `pull.merged`, …) to the bus and does not
Workspaces own repositories1771 call other services to react. Each subscriber consumes from its own queue.
1772 Timelines, webhooks and automations read the same stream, which is what
1773 lets something like GitHub Actions be built on top.
1774- **Every read takes the viewer.** Authorization is decided inside the
1775 service that owns the data, not by its callers.
1776
1777The Workers runtime scales request handling on its own, so the edge layer
1778stays in TypeScript. Rust is used where there is real computation or a real
1779protocol to implement.
1780
1781## Languages
1782
1783The site is TypeScript. Everything behind it is Rust, compiled to
API and MCP server in Rust; a public index at the API root1784WebAssembly for Workers and natively for containers and the CLI. Identity, repos, work, events and the API are all Rust. The one exception
1785is the Worker that starts sandboxes, because Cloudflare's Containers
1786library is TypeScript. Rust services speak a
Workspaces own repositories1787small JSON protocol over service bindings (`POST /rpc/<method>`), with the
1788types in `crates/contracts`.
1789
1790## Identifiers
1791
1792Every id is a [TypeID](https://github.com/jetify-com/typeid): a prefix naming
1793the kind of thing, then a UUIDv7 in lowercase base32, such as
Issues and pull requests replace intents and attempts1794`pr_01jb2k7x9hfq0b3zj0f5s2m8ra`.
Workspaces own repositories1795
1796- The prefix makes an id self-describing and stops ids of different kinds
1797 being mixed up.
1798- Ids sort by creation time as plain strings. In SQLite (D1 and Durable
1799 Objects) that keeps inserts at the end of the primary-key index instead of
1800 scattering them, and gives time-ordered paging for free.
1801- The suffix decodes to a standard UUIDv7 for any system that wants one.
1802- Ids are made by the service that creates the record, not by the database,
1803 so they work across services and can be assigned before a write.
1804
1805## Events at scale, and audit
1806
1807The current event log is a single D1 database. That is fine for a
1808prototype and wrong for the target: D1 is one writer and 10 GB. The design
1809for volume splits storage by how the data is read.
1810
1811| Tier | Store | Holds | Read by |
1812| --- | --- | --- | --- |
1813| Hot | A Durable Object per repository, with SQLite | Recent events for that repo | Timelines, live pages over WebSocket |
1814| Complete | Cloudflare Pipelines into R2 as Apache Iceberg | Every event, forever, partitioned by day and workspace | Analytics, standups, "ask", export |
1815| Audit | The same R2 store, under object lock | Who did what, from where, with which credential | Compliance, investigation |
1816
1817- **No single hot database.** Each repository's recent events live with that
1818 repository, so load spreads across as many objects as there are repos.
1819- **The complete record is files, not rows.** Iceberg on R2 has no practical
1820 size limit and is queried with SQL.
1821- **Audit is a property of every event.** The envelope carries the actor
1822 (person, agent, token or system), the credential used, the request id and
1823 the source address. Audit entries for a workspace are hash-chained, so a
1824 removed or altered entry is detectable, and are written under a retention
1825 lock.
1826- **Delivery is at least once.** Consumers are idempotent on the event id.
1827
1828## Accounts and forge basics
1829
1830- Registration with email verification, sign-in, forgot password (Cloudflare
1831 Email Sending), Turnstile on public forms.
1832- GitHub sign-in, SSH keys, access tokens, active sessions.
1833- Profiles, public and private repositories, repository search (D1 full-text).
1834- Rendered README, syntax highlighting, commit history, diffs.
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look1835- Transferring a repository between workspaces (by id: its git store key
1836 never moves; every service follows `repo.transferred`; old paths redirect
1837 until reused) and deleting an empty, settled workspace (its slug is
1838 tombstoned, never reissued except to the person whose username it is).
Merge main (membership, two-factor, GitHub repo roles) into tokens1839- Access: five repository roles (Read, Triage, Write, Maintain, Admin;
1840 the capability table follows GitHub's repository roles, 2026-10-08:
1841 branch protection and rulesets are Admin, labels and milestones are made
1842 with Write and applied with Triage, security alerts are Write), a
1843 workspace base permission (Read for new workspaces), the creator of a
1844 repository given Admin on it, outside collaborators and invitations.
1845 Membership as GitHub's organizations have it (2026-10-08): owners and
1846 members, promote and demote, transfer ownership, leave, a last-owner
1847 guard; billing manager and security manager on top of member; member
1848 privileges (who creates public and private repositories, whether
1849 repository admins change visibility, delete and transfer, and invite
1850 outside collaborators); two-factor authentication (TOTP and recovery
1851 codes) and a workspace policy that requires it, holding non-compliant
1852 people out until they turn it on. Every membership change, token, SSH
1853 key, OAuth grant and two-factor change is in the audit log. Teams are built on it (2026-10-07): visible
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1854 or secret, nested up to 8 levels (child teams inherit their parents'
1855 roles), run by maintainers and owners. A team's role on a repository is a
1856 `repo_grants` row whose principal is the team, which identity resolves
1857 into the same `RepoGrant`s on each person, so `access::can` needs nothing
1858 new: the highest role wins. `@workspace/team` mentions tell the team's
1859 people; a team asked to review either asks everyone or picks people by
1860 round robin or load balance.
1861- CODEOWNERS, read in both conventions (single-section, and sections with
1862 approval counts, optional sections and default owners) from the first of
1863 `.g1t/`, `.github/`, the root, `docs/` and `.gitlab/`. Owners are asked to
1864 review, the `g1t / codeowners` status lints a changed file, and branch
1865 protection's "Require review from code owners" holds merges, for people,
1866 agents and the queue alike, until each owning rule is approved.
Workspaces own repositories1867
1868## Built on Cloudflare
1869
1870| Need | Product |
1871| --- | --- |
Issues and pull requests replace intents and attempts1872| Repositories; a fork per pull request; data residency per workspace | Artifacts (forks, jurisdictions) |
Workspaces own repositories1873| Reacting to pushes | Artifacts event subscriptions on Queues |
Plan: a repository that maintains itself, and deployments on g1t.page1874| Preview URL per pull request; deploy on merge | Workers for Platforms on `g1t.page` |
Workspaces own repositories1875| Site, API, MCP, git front end | Workers |
1876| Per-repo coordination, live updates | Durable Objects |
Issues and pull requests replace intents and attempts1877| Pull request lifecycles, automations | Workflows, Cron Triggers |
Workspaces own repositories1878| Agent sandboxes, SSH server, merge engine | Sandbox SDK and Containers |
1879| Fast starts on large repos | ArtifactFS |
1880| Model traffic, spend, budgets | AI Gateway |
1881| Summaries, embeddings | Workers AI |
1882| Context hub search | Vectorize |
1883| Accounts and metadata | D1 |
1884| Transcripts and logs | R2 |
1885| Email, bot protection, keys | Email Sending, Turnstile, Secrets Store |
1886
Running g1t yourself: the design, a docker compose proof, and a guide to what works today1887## Running g1t yourself
1888
1889g1t.sh runs on Cloudflare, and that does not change. The core is MIT and
1890must also run on anyone's own machine with `docker compose up`. A free
1891core people can self-host is what makes paid hosting worth trusting.
1892Self-hosting never makes hosted worse: hosted code paths keep their
1893behaviour, and a self-hosted adapter sits beside the hosted one. The
1894inventory of every Cloudflare dependency, the design and the risks are in
1895[SELF_HOSTING.md](SELF_HOSTING.md).
1896
1897The approach: the Workers stay Workers, and self-hosted they run in
1898workerd, the open-source Workers runtime. D1, KV and Queues are SQLite on a
1899volume, with the same migrations. Cloudflare-only bindings are replaced
1900by stand-ins:
1901
1902- Artifacts becomes bare repositories served by `git http-backend`;
1903- Email Sending becomes SMTP, through Mailpit;
1904- services that are off answer "off" instead of failing.
1905
1906| Phase | Scope | Estimate |
1907| --- | --- | --- |
1908| 1. Core forge | Done: `deploy/self-host/` (compose, git store, binding stand-ins, smoke test) and the "Run g1t yourself" guide. Left: the API on its own port, `PUBLIC_URL` in place of hard-coded hosts, cron, pull requests in the smoke test, CI that runs it. | 1–1.5 weeks left |
1909| 2. Agents | Docker sandboxes with the same runner image, an egress allow-list proxy for guardrails, `g1t.toml`, a launcher in place of `wrangler dev` | 2–3 weeks |
1910| 3. Search, context, deployments | sqlite-vec plus an OpenAI-compatible embedder; an app host on workerd; Caddy for app and custom domains; SSH | 3–4 weeks |
1911| 4. Parity and upgrades | Code-level ports in `g1t_kit` and `@g1t/platform`, sudo without Access, online backups, released images, an upgrade test in CI | 3–4 weeks |
1912
Workspaces own repositories1913## The submission
1914
1915- **g1t is built on g1t.** This repository is hosted on g1t.sh, its features
Issues and pull requests replace intents and attempts1916 are opened as issues and built by racing agents, and it deploys from
Workspaces own repositories1917 Artifacts through Workers Builds. The history is the proof.
Issues and pull requests replace intents and attempts1918- **The demo follows one story.** A brief becomes a project; twelve issues
Workspaces own repositories1919 fan out to dozens of agents; agents notice each other, hand off, and
1920 resolve a conflict; reviewers triage; the queue lands everything on
1921 `main`; why-blame explains a line; the portfolio shows where it all
1922 stands. Then the same thing at a thousand agents.
1923- **Judges can try it in a minute.** Open registration on g1t.sh, one-click
1924 import of a GitHub repo, one command to connect Claude Code, a seeded demo
1925 workspace, and a single deploy command for running their own copy.
1926- **The formats are open.** The commit trailers, session format and runner
1927 contract are published so other tools can interoperate.
1928
1929## Build order
1930
Agents as a team: lifecycle, merge queue, billing and a new shell1931What is left is ordered by how much it shows the point above, not by forge
1932parity. Forge basics are done well enough; each item below should make the
1933demo's story stronger.
1934
Plan: what is done from the agent-first list, and what is next1935Done from this list: the outcome page (a plan's issues as a live graph with
1936cost and a feed of what happened), coordination you can see (agents' issues
1937and comments stand out in the feed; agents hold g1t's tools through a token
1938scoped to one repository), steering a running agent (messages delivered
1939between steps, and at the end), and recording sessions from anyone's own
Plan: integrations are in1940Claude Code (`curl -fsSL https://g1t.sh/install/claude.sh | sh`). Integrations are
1941in: a workspace's own model provider (Anthropic or any Anthropic-compatible
Prices are what g1t pays plus 20%, from the first second1942endpoint, reached through a model proxy so no sandbox holds a key; its
1943runs pay only their sandbox time), alerts from Sentry, Datadog and signed webhooks
Plan: integrations are in1944that open one issue per problem and can start an agent, and Jira and Linear
1945tickets that agents read, people import, and that hear back. Racing a
Plan: what is done from the agent-first list, and what is next1946set number of agents on one issue is dropped: choosing how many agents to
1947use is not something people should have to do.
Agents as a team: lifecycle, merge queue, billing and a new shell1948
Agents asked while not at work are woken to answer19491. ~~**Handoffs and questions between agents** as states on the outcome
1950 page.~~ Done: questions and handoffs show as waiting, read, answered,
1951 taken on or declined; since 2026-10-03 an agent asked while it is not at
1952 work is woken to answer, where before the question waited forever.
Plan: a repository that maintains itself, and deployments on g1t.page19532. **Upkeep agents** (above): dependency updates, secret scanning,
1954 vulnerability alerts, code scanning, the security page. No new
1955 infrastructure.
19563. **Deployments on `g1t.page`** (above): previews per pull request,
1957 production on merge, the reviewer agent checking the preview.
19584. **The large run, building 2 and 3.** About 20–30 issues on g1t itself,
1959 built by agents and landed through the queue, for the video: g1t built
1960 on g1t.
19615. **Polish for judges trying it in a minute:** a seeded demo workspace, the
Plan: what is done from the agent-first list, and what is next1962 empty states, and the first-run path from sign-up to an outcome landing.
Workspaces own repositories1963
Agents as a team: lifecycle, merge queue, billing and a new shell1964Earlier items still open, after those:
1965
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar19661. Deleting a branch once its pull request merges; risk tiers. (Approval
1967 rules per path are in, as CODEOWNERS.)
Merge main (membership, two-factor, GitHub repo roles) into tokens19682. Event storage per the design above: per-repo hot log, Iceberg on R2,
API and MCP server in Rust; a public index at the API root1969 hash-chained audit.
Merge main (membership, two-factor, GitHub repo roles) into tokens19703. CLI with Claude Code hooks to record sessions automatically.
19714. Reviewing and catching up automatically, by policy; required reviews;
Agents as a team: lifecycle, merge queue, billing and a new shell1972 risk tiers.
Merge main (membership, two-factor, GitHub repo roles) into tokens19735. Compare view, proof bundles; handoff between agents.
19746. Projects, mission control, steering; why-blame, digest, timeline.
19757. Context hub, portfolio; automations and integrations (Sentry first).
19768. SSH; bot protection; own keys, endpoints and runners.
19779. Large run (100+ agents across many issues), hardening, demo.
197810. Passkeys (WebAuthn) as a second factor and for signing in: feasible on
1979 Workers (P-256 and RS256 verification in Rust, or WebCrypto), next
1980 after TOTP. Then fine-grained tokens, deploy keys and package access.
Workspaces own repositories1981
Merge main (membership, two-factor, GitHub repo roles) into tokens1982Later: code search, mirroring to GitHub, SSH
Workspaces own repositories1983on port 22 without the CLI proxy (needs the Workers inbound TCP private
1984beta).

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