| 1 | --- |
| 2 | title: Claims and dependencies |
| 3 | description: How people and coding agents work on the same work items without colliding. Advisory claims and hand-offs, what a work item is blocked by, overlapping changes, the coordination updates each session receives, and the events behind them. |
| 4 | --- |
| 5 | |
| 6 | When several agents and people work in one workspace at once, each needs |
| 7 | to know what the others are doing. g1t keeps that around the |
| 8 | [work item](/work/work-items/), the unit of work, and around the |
| 9 | [sessions](/work/sessions/) working on it: |
| 10 | |
| 11 | - **Claims**: an advisory, expiring "I'm working on #12". Never a lock. |
| 12 | - **Hand-offs**: "I'm stopping; here is where it stands". |
| 13 | - **Dependencies**: the work items that have to land before this one. |
| 14 | - **Overlaps**: two pull requests, or two sessions, changing the same files. |
| 15 | |
| 16 | Each change is announced as an event, and as a |
| 17 | [coordination update](#coordination-updates) to the sessions it concerns, |
| 18 | so an agent hears about it between steps instead of finding out at merge |
| 19 | time. |
| 20 | |
| 21 | ## Claims |
| 22 | |
| 23 | A claim says you are working on a work item. It is advisory: anyone may |
| 24 | claim a work item someone else has, and is told about them, so two agents |
| 25 | can decide between themselves rather than collide. Nothing is refused |
| 26 | because of a claim. A claim is the workspace's, whichever repository the |
| 27 | session that holds it is checked out in, so sessions in different |
| 28 | repositories see each other's claims on the same work item. |
| 29 | |
| 30 | - **Claim** an open work item with `work_item` `claim`, `g1t work claim 12` |
| 31 | (with `--note` to say what you are taking), or |
| 32 | [`POST /workspaces/{workspace}/work/{number}/claim`](/reference/api/work-items/claim-work-item/). |
| 33 | Give your `session_id`, so that two of your sessions, such as sibling |
| 34 | subagents, hold claims of their own and each is told of the other's. The |
| 35 | answer has your `claim`, the `others` already on the work item, and |
| 36 | `blocked_by`: each work item this one waits on, with its claims and pull |
| 37 | requests. A closed work item cannot be claimed (`409`). |
| 38 | - **File a work item and claim it** in one step, for work that has no work |
| 39 | item yet: `work_item` `claim` with `title` (and `body`) and no `number`, |
| 40 | `g1t work claim --title "…"`, or |
| 41 | [`POST /workspaces/{workspace}/claims`](/reference/api/work-items/claim-new-work-item/). |
| 42 | The work item is filed (a `work_item.opened` event), with the session's |
| 43 | repository as its origin when you give `repo`, then claimed, and the |
| 44 | session named by `session_id` is attached to it. The answer also has |
| 45 | `item`, the work item filed. The session is checked first: a claim that |
| 46 | would be refused for it files nothing. |
| 47 | - **Renew** it by claiming again, or give the `session_id` of your session |
| 48 | when you claim, and that session's heartbeats renew it. |
| 49 | - **Release** it with `work_item` `release`, `g1t work release 12`, or |
| 50 | [`POST /workspaces/{workspace}/work/{number}/release`](/reference/api/work-items/release-claim/), |
| 51 | with an optional `reason`. |
| 52 | - **Hand it off** with `work_item` `handoff`, `g1t work handoff 12 --note |
| 53 | "…"`, or |
| 54 | [`POST /workspaces/{workspace}/work/{number}/handoff`](/reference/api/work-items/hand-off-work-item/), |
| 55 | with a `note` on where the work stands, for `to` (a username) or anyone. |
| 56 | When whoever it was for claims the work item, their `work.claimed` event |
| 57 | names the hand-off in `took_over`. |
| 58 | |
| 59 | ```sh |
| 60 | curl -X POST https://api.g1t.sh/workspaces/acme/work/12/claim \ |
| 61 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 62 | -H "Content-Type: application/json" \ |
| 63 | -d '{"session_id": "ses_01m4b2c3d4e5f6g7h8j9k0m1n2", "note": "Taking the argument parsing first."}' |
| 64 | |
| 65 | curl -X POST https://api.g1t.sh/workspaces/acme/claims \ |
| 66 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 67 | -H "Content-Type: application/json" \ |
| 68 | -d '{"session_id": "ses_01m4b2c3d4e5f6g7h8j9k0m1n2", "repo": "acme/web", "title": "Preview builds time out on large repositories"}' |
| 69 | ``` |
| 70 | |
| 71 | | | | |
| 72 | | --- | --- | |
| 73 | | How long a claim lasts | `ttl_minutes`: 30 unless you say, at most 240 (`--ttl 2h` on the CLI). | |
| 74 | | Filing its work item | `title` (and `body`) instead of `number`. Giving both is refused with `422`. | |
| 75 | | When it ends | Released, handed off, its work item closed (`reason` `item_closed`), or not renewed in time (`expired`). | |
| 76 | | States | `active`, `released`, `expired`, `handed_off`. | |
| 77 | |
| 78 | See who is on what with `work_item` `list_claims`, `g1t work status`, or |
| 79 | [`GET /repos/{owner}/{name}/claims`](/reference/api/work-items/list-claims/): |
| 80 | active claims unless `state` says otherwise, and `item` for one work |
| 81 | item's. On the site, a work item's **Work** panel lists its claims: who, |
| 82 | from which harness, since when and when each lapses, with those released, |
| 83 | expired or handed off lately dimmed. A work item with nobody on it says |
| 84 | how to claim it. |
| 85 | |
| 86 | ## Dependencies |
| 87 | |
| 88 | A work item's `blocked_by` lists the work items of the same workspace that |
| 89 | have to land before it. On its page, **Edit** beside **Blocked by** in the |
| 90 | Work panel changes it. From the CLI: |
| 91 | |
| 92 | ```sh |
| 93 | g1t work block 12 --by 9 --by 10 |
| 94 | g1t work unblock 12 --by 10 |
| 95 | ``` |
| 96 | |
| 97 | Over MCP and the API, `work_item` `update` or |
| 98 | [`PATCH /workspaces/{workspace}/work/{number}`](/reference/api/work-items/update-work-item/) |
| 99 | replaces the whole list: |
| 100 | |
| 101 | ```sh |
| 102 | curl -X PATCH https://api.g1t.sh/workspaces/acme/work/12 \ |
| 103 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 104 | -H "Content-Type: application/json" \ |
| 105 | -d '{"blocked_by": [9, 10]}' |
| 106 | ``` |
| 107 | |
| 108 | A list is refused with `422` when a number is not a work item of the |
| 109 | workspace, names the work item itself, or would make a cycle (the answer |
| 110 | shows the cycle, such as `#12 → #9 → #12`). Up to 50 work items. Changing |
| 111 | it notes the change in the work item's conversation (**marked this as |
| 112 | blocked by #9**) and needs what editing the work item does: being its |
| 113 | owner, or the Triage role. |
| 114 | |
| 115 | The Work panel shows what a work item is blocked by and where each of |
| 116 | those stands, and the work items it blocks. g1t says when a dependency |
| 117 | moves, as a `dependency.changed` event on the blocked work item: when its |
| 118 | list changes, and when one of its blockers closes or has a pull request |
| 119 | merged into the default branch. `remaining` lists the blockers still open; |
| 120 | when it is empty, the work item is unblocked. |
| 121 | |
| 122 | ## Overlaps |
| 123 | |
| 124 | Opening a pull request, and each push to it, works out which files it |
| 125 | changes. When it starts changing files another open or draft pull request |
| 126 | changes, g1t sends `overlap.detected` once for each of the two, naming the |
| 127 | other and the files. A pair is announced once, and again only after it |
| 128 | stopped overlapping. A pull request's `overlaps`, in `pull_request` `get` |
| 129 | and in the work item's [work context](/work/agents/#pick-up-a-work-item), |
| 130 | show current overlaps whenever you look. |
| 131 | |
| 132 | Sessions overlap too, before there is a pull request: when a session says |
| 133 | it touched a file that another active session touched (outside its own |
| 134 | parents and subagents), each gets `overlap.detected` with `session_id`, |
| 135 | `other_session_id`, `other_actor` and `files`, once per pair, and again |
| 136 | with the new `files` when another file in common joins. |
| 137 | |
| 138 | An overlap with a pull request for a different work item will become a |
| 139 | conflict for whichever merges second: narrow the change, agree an order, |
| 140 | or say so in the pull request. |
| 141 | |
| 142 | ## Coordination updates |
| 143 | |
| 144 | Each session has an inbox of coordination updates: the claims, releases, |
| 145 | hand-offs and expiries, overlaps, dependency changes, decisions, |
| 146 | merge-queue results and sessions starting and ending that concern it. They |
| 147 | work the same with Claude Code, Codex or any other harness: |
| 148 | |
| 149 | ```sh |
| 150 | g1t session updates --json |
| 151 | g1t session acknowledge upd_ID --note "My scope is separate; no plan change" |
| 152 | ``` |
| 153 | |
| 154 | They use `G1T_SESSION` (or the working copy's remembered session). |
| 155 | `session updates`, `session acknowledge` and `session heartbeat` first say |
| 156 | which files the working copy has changed (from `git status`), as |
| 157 | `session touch --file` would, so overlapping edits are noticed whichever |
| 158 | harness makes them; `G1T_TOUCH=0` turns that off. In a shared checkout, |
| 159 | `updates SESSION_ID` and `acknowledge --session SESSION_ID` name the |
| 160 | session. Over MCP, `session` `get` returns up to 100 pending `updates`, |
| 161 | oldest first, separately from the session's entries; the API's |
| 162 | `get_session` does the same (give `after=4294967295` to leave the entries |
| 163 | out). |
| 164 | |
| 165 | An active session receives the updates that concern it: |
| 166 | |
| 167 | | The session is | It receives | |
| 168 | | --- | --- | |
| 169 | | Attached to a work item or pull request, or tied to one (a claim, its branch, a `#N` it named) | Updates about that work item or pull request: its claims, decisions, overlaps, dependency changes and merge-queue results, and those that name it, such as an integration failure listing it as a suspect or a work item newly blocked by it | |
| 170 | | Not on anything yet | Every update, so it can find who else is working and on what | |
| 171 | | Either | Updates about nothing in particular, such as a session starting without a work item; and an overlap between its own files and another session's, which goes only to the two sessions | |
| 172 | |
| 173 | A session does not receive its own start or end, or the claims it made, |
| 174 | released or handed off. It does hear when its claim expires. A new session |
| 175 | should still load the work item's context: an inbox is not a replay of |
| 176 | what happened before the session started. |
| 177 | |
| 178 | Reading does not clear an update. After considering it, and recording any |
| 179 | change of plan, the session acknowledges the exact IDs it considered: |
| 180 | `g1t session acknowledge`, the MCP `session` tool's `record` with |
| 181 | `acknowledge`, or |
| 182 | |
| 183 | ```sh |
| 184 | g1t api record_session_entries -f id=SESSION_ID -f 'acknowledge[]=UPDATE_ID' |
| 185 | ``` |
| 186 | |
| 187 | Repeat the field for more IDs, at most 100 a request, then read again for |
| 188 | the next page. Acknowledging is idempotent and scoped to that session. It |
| 189 | means considered, not resolved. The answer's `acknowledged` says how many |
| 190 | of the IDs name updates of that session, so a mistyped ID or one from |
| 191 | another session shows up as a shortfall (the CLI warns). A session's page |
| 192 | shows what it has not acknowledged. |
| 193 | |
| 194 | The [Claude Code plugin](/guides/claude-code-plugin/)'s hooks fetch |
| 195 | updates in the background, at most once every ten seconds, and at once |
| 196 | after an acknowledgement. Every prompt shows what is pending; before a |
| 197 | tool, pending updates are shown when they change and again every two |
| 198 | minutes, until acknowledged. Other harnesses, including sessions g1t runs, |
| 199 | read them between work steps, as the coordinate skill says. Neither a |
| 200 | disconnected harness nor an idle session is interrupted. |
| 201 | |
| 202 | An update is written in the same transaction as the change it announces: |
| 203 | a claim, release, hand-off, expiry, session start or end, overlap, |
| 204 | decision or change to what a work item is blocked by is never kept without |
| 205 | its updates, and updates never announce a change that was not made. Each |
| 206 | update's ID is derived from its change, so a retried request, or two |
| 207 | requests making the same change at once, delivers it once. The one |
| 208 | exception is the notice that a work item's blocker closed or merged, which |
| 209 | follows the close or merge: it is written right after, once per close or |
| 210 | merge. Updates are still a summary: read the work item and pull request |
| 211 | again before acting on one. |
| 212 | |
| 213 | Acknowledged updates are kept as receipts for 30 days. Pending updates |
| 214 | stay until acknowledged, including those of a session that ended, so |
| 215 | whoever takes over its work can see what it never considered. |
| 216 | |
| 217 | ## Events |
| 218 | |
| 219 | Coordination is published as events, which [webhooks](/guides/webhooks/) |
| 220 | deliver and Sessions' **What happened** lists. Each carries `number` (the |
| 221 | work item or pull request it is about) and `item` (the work item's number |
| 222 | in the workspace) where there is one. |
| 223 | |
| 224 | | Event | When | |
| 225 | | --- | --- | |
| 226 | | `session.started` | A session (or a subagent) starts, or one that ended starts again. Not on a repeated start. | |
| 227 | | `session.ended` | A session ends, or times out after 30 minutes without a heartbeat. | |
| 228 | | `session.progressed` | A session recorded more: at most every 5 seconds for each, with `session_id` (and `root_id` for a subagent), never what it recorded. Pages showing the session follow it with this. | |
| 229 | | `work.claimed` | Someone claims a work item. `others` lists the claims already on it; `took_over` names a hand-off it takes. | |
| 230 | | `work.released` | A claim is released, or its work item closed (`reason` `item_closed`). | |
| 231 | | `work.claim_expired` | A claim was not renewed in time. | |
| 232 | | `work.handoff_requested` | Someone hands a work item off: `from`, `to` (absent for anyone) and `note`. | |
| 233 | | `dependency.changed` | A work item's `blocked_by` changed (`added`, `removed`), or a blocker closed or had its pull request merged (`cleared`). `remaining` lists the blockers still open. | |
| 234 | | `overlap.detected` | A pull request started changing files another open one changes: `pull`, `other_pull`, `files`, `item` and `other_item`. Or a session touched files another active session touched: `session_id`, `other_session_id`, `other_actor`, `files`. | |
| 235 | |
| 236 | A session or claim that went quiet is announced as ended or expired when |
| 237 | the repository's sessions or claims are next read or changed, not at the |
| 238 | minute it lapsed. |
| 239 | |
| 240 | ## Who may do what |
| 241 | |
| 242 | | To | You need | |
| 243 | | --- | --- | |
| 244 | | Read sessions and claims | To be able to read the repository. Public repositories need no token. What a session shows depends on who you are: see [who sees what](/work/sessions/#who-sees-what). | |
| 245 | | Read a workspace's **Sessions** | It lists the sessions of the workspace's repositories you can read; g1t's own agent's sessions only for members. | |
| 246 | | Read a work item's context | To be able to see the work item: see [who sees a work item](/work/work-items/#who-sees-a-work-item). | |
| 247 | | Start a session, claim a work item, file one by claiming it | A confirmed email address and a role that may file work items; the repository must not be archived. | |
| 248 | | Update, record in or end a session | To be the person whose token started it. Ending one by hand: also anyone with write access. | |
| 249 | | Release a claim or hand it off | To be the person who made it. | |
| 250 | | Set `blocked_by` | To be the work item's owner, or the Triage role. | |
| 251 | |
| 252 | With an access token, sessions need `pull_requests:read` or |
| 253 | `pull_requests:write`, and claims and the work context need `work:read` or |
| 254 | `work:write`, as [scopes](/guides/authentication/#scopes) say. |