| 1 | --- |
| 2 | title: Sessions, claims and dependencies |
| 3 | description: How agents and people on one repository see who is working on what, with sessions of their own harnesses, advisory claims on issues, what an issue is blocked by, and the one call that loads an issue's whole context. |
| 4 | --- |
| 5 | |
| 6 | When several agents and people work on one repository at once, each needs |
| 7 | to know what the others are doing. g1t keeps that around the issue, which |
| 8 | is the unit of work: its description says what is wanted and what done |
| 9 | means, its pull requests are the proposals, and around it g1t records: |
| 10 | |
| 11 | - **Sessions**: one run of your own harness (a Claude Code session, a |
| 12 | Codex run) on the repository, attached to the issue and pull request it |
| 13 | works on. |
| 14 | - **Claims**: an advisory, expiring "I'm working on #12". Never a lock. |
| 15 | - **Dependencies**: the issues that have to land before this one. |
| 16 | |
| 17 | Until there is an issue, the session is the unit: work that starts from a |
| 18 | question or a quick request is recorded as a session titled with what it |
| 19 | is for, and shows to the team on its branch or pull request. It opens or |
| 20 | claims an issue only when it becomes a change others should know about; |
| 21 | see [Work with no issue yet](#work-with-no-issue-yet). |
| 22 | |
| 23 | Nothing here waits on a harness. A harness that crashes, loses its |
| 24 | network or sends the same thing twice does no harm: sessions and claims |
| 25 | that go quiet are read as idle, ended or expired the next time anyone |
| 26 | looks, and starting a session or recording an entry again is a no-op. |
| 27 | What git and g1t record (commits, pull requests, checks, merges) is the |
| 28 | truth; sessions are the account of how it got there. |
| 29 | |
| 30 | ## On the site |
| 31 | |
| 32 | Everything here shows on g1t.sh as it happens, without reloading. |
| 33 | |
| 34 | - **The Work page**, `g1t.sh/<workspace>/<repo>/work`, a tab beside |
| 35 | **Pull requests**, **Merge queue** and **Sessions**: |
| 36 | - **Live now**: the active claims and the active and idle sessions, |
| 37 | grouped by the issue they are on, the most recently active first. An |
| 38 | issue with more than one claim is marked. Sessions on no issue yet |
| 39 | follow, grouped by their pull request, else by their branch (when it |
| 40 | is not the default branch), the most recently heard from first; those |
| 41 | on neither are last, under **No branch yet**. Each session shows its |
| 42 | title, who it acts for, its harness, its state, when it was last heard |
| 43 | from and its branch. A session with no title is named by what its |
| 44 | first prompt was for, else **Session on** its branch, else **Untitled |
| 45 | session**. |
| 46 | - **Merge queue**: what is waiting to land and what is being tested, |
| 47 | as on the [Merge queue](/guides/merge-queue/#the-merge-queue-page) page. |
| 48 | - **What happened**: the latest 30 coordination events, from claims to |
| 49 | what the merge queue found when it combined changes. |
| 50 | - **Just landed**: the latest merges, each with a link to the session |
| 51 | behind it. |
| 52 | |
| 53 | With nothing going on, it says how to start: install the |
| 54 | [Claude Code plugin](/guides/claude-code-plugin/), or run |
| 55 | `g1t work claim <number>` from any harness. |
| 56 | - **An issue's Work panel**, at the top of its sidebar: its claims (who, |
| 57 | from which harness, since when and when each lapses; ones released, |
| 58 | expired or handed off lately are shown dimmed), the sessions on it with |
| 59 | their state and when each was last heard from, what it is blocked by |
| 60 | and where each of those stands, and the issues it blocks. Its author |
| 61 | and anyone with the Triage role change what it is blocked by with |
| 62 | **Edit**. Under its pull requests, the issue shows the latest |
| 63 | combination that failed in the merge queue, and its |
| 64 | [decision records](/guides/why-blame/#decision-records), each marked |
| 65 | **Claimed**, **Tested** or **Approved**. |
| 66 | - **A session's page**, `g1t.sh/<workspace>/<repo>/work/sessions/<id>`, |
| 67 | opened from any of these: who ran it, in which harness and on which |
| 68 | model, how long it has run, the issues and pull requests it and its |
| 69 | subagents worked on (each says how it was tied), its subagents as a tree |
| 70 | you open one at a time (each with its kind, the task it was given, what |
| 71 | it touched and what it reported), the skills used, what was touched |
| 72 | (files, commits, branches, pull requests), and everything it recorded, |
| 73 | as it records it. A subagent's own page links back to the session that |
| 74 | started it. |
| 75 | - **An issue's and a pull request's sessions**: every session tied to it |
| 76 | in any way, with its subagents under it. |
| 77 | - **Start a session** on an issue, for members of a workspace with an |
| 78 | Anthropic AI provider: see |
| 79 | [Start a session on your Anthropic account](#start-a-session-on-your-anthropic-account). |
| 80 | |
| 81 | ## Picking up an issue |
| 82 | |
| 83 | Before working on an issue, load its whole context in one call: `issue` |
| 84 | with `"action": "work"` over MCP, or |
| 85 | [`GET /repos/{owner}/{name}/issues/{number}/work`](/reference/api/claims-and-work/get-work/): |
| 86 | |
| 87 | ```sh |
| 88 | curl https://api.g1t.sh/repos/acme/web/issues/12/work \ |
| 89 | -H "Authorization: Bearer $G1T_TOKEN" |
| 90 | ``` |
| 91 | |
| 92 | | Field | What it holds | |
| 93 | | --- | --- | |
| 94 | | `issue` | The issue, with its body. | |
| 95 | | `definition_of_done` | The items under its **Definition of done** heading. | |
| 96 | | `required_checks` | The checks every pull request into the default branch must pass. | |
| 97 | | `claims` | Who says they are working on it now. | |
| 98 | | `sessions` | Sessions on it or its pull requests, or tied to it any other way, subagents included, active ones first. Each says how many `subagents` it started. | |
| 99 | | `pulls` | Its pull requests. Those still open or draft carry their `required_checks` as they stand on the head, `mergeable`, the other pull requests they `overlap`, and their place in the merge `queue`. | |
| 100 | | `blocked_by` | Each issue it waits on, with that issue's claims and pull requests. | |
| 101 | | `blocks` | The issues waiting on it. | |
| 102 | | `decisions` | [Decision records](/guides/why-blame/#decision-records) on it and its pull requests, newest first. | |
| 103 | | `last_integration_failure` | The latest `integration_failure` decision among them, if any: the combination that failed in the merge queue, the check, the `suspects` and, when it failed on `main` alone, the pull requests that `landed` on `main` since it branched. | |
| 104 | | `recent` | Its latest 20 coordination events, newest first. | |
| 105 | |
| 106 | Then claim it, and start (or attach) your session. |
| 107 | |
| 108 | ## Sessions |
| 109 | |
| 110 | A session is one run of your harness on a repository. Start one when the |
| 111 | harness starts, keep it alive while it works, and end it when it stops. |
| 112 | |
| 113 | 1. **Start** it with `session` `start`, or |
| 114 | [`POST /repos/{owner}/{name}/sessions`](/reference/api/sessions/start-session/), |
| 115 | naming the `harness` (`claude_code`, `claude_managed_agents`, `codex`, |
| 116 | `cursor`, `copilot` or `other`) and the harness's own id for the session as |
| 117 | `harness_session_id`. Starting again with the same id returns the |
| 118 | session already started, so a hook can call it every time without |
| 119 | checking first. Give `issue`, `pull` and `branch` when you know them, |
| 120 | and a `title`: what the session is for, in a few words (up to 200 |
| 121 | characters). |
| 122 | 2. **Heartbeat** with `session` `update`, or |
| 123 | [`PATCH /repos/{owner}/{name}/sessions/{id}`](/reference/api/sessions/update-session/) |
| 124 | with an empty body. The same call attaches the session to an issue or |
| 125 | pull request, records the `head_commit` it pushed, or changes its |
| 126 | `title`. |
| 127 | 3. **Record** what happens with `session` `record`, or |
| 128 | [`POST /repos/{owner}/{name}/sessions/{id}/entries`](/reference/api/sessions/record-session-entries/): |
| 129 | prompts, reasoning, tool calls, notes and the skills it used (`skill`, |
| 130 | the skill's name only), up to 200 a request, and in `touched` what it |
| 131 | touched (see [What a session worked on](#what-a-session-worked-on)). |
| 132 | Give each entry a `key`, and recording it again does nothing. |
| 133 | 4. **End** it with `session` `end`, or |
| 134 | [`POST /repos/{owner}/{name}/sessions/{id}/end`](/reference/api/sessions/end-session/), |
| 135 | with its `result` when it has one: what it reported when it finished. |
| 136 | |
| 137 | ```sh |
| 138 | curl -X POST https://api.g1t.sh/repos/acme/web/sessions \ |
| 139 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 140 | -H "Content-Type: application/json" \ |
| 141 | -d '{"harness": "claude_code", "harness_session_id": "5b0c1f9e-3d2a-4e8b-9f61-0c7d2a9e4b13", "issue": 12}' |
| 142 | ``` |
| 143 | |
| 144 | A session's `state` is worked out from when it was last heard from. Every |
| 145 | update and every batch of entries counts as a heartbeat: |
| 146 | |
| 147 | | State | Means | |
| 148 | | --- | --- | |
| 149 | | `active` | Heard from in the last 15 minutes. | |
| 150 | | `idle` | Not heard from for 15 minutes. It may still come back. | |
| 151 | | `ended` | Ended with `end_session`, or not heard from for 2 hours (`end_reason` `timed_out`). A heartbeat brings a timed-out session back; an ended one stays ended. | |
| 152 | |
| 153 | Entries of a session attached to a pull request show in that pull |
| 154 | request's [session](/guides/why-blame/#sessions), beside what was recorded |
| 155 | on it with `record_session`, so reviewers and why-blame see them. Entries |
| 156 | recorded before the session named its pull request move onto it when it |
| 157 | does. A session never records tool output unless you send it as a |
| 158 | `tool_result` entry; a session is as visible as the repository, so keep |
| 159 | secrets out of it. |
| 160 | |
| 161 | List a repository's sessions with `session` `list`, or |
| 162 | [`GET /repos/{owner}/{name}/sessions`](/reference/api/sessions/list-sessions/) |
| 163 | by `state`, `issue` or `pull` (any session tied to it), or `path` (those |
| 164 | that touched a file, or any under a folder ending in `/`); subagents are |
| 165 | listed too with `subagents=true`. A session in the list with no `title` |
| 166 | carries `first_prompt`: the first 300 characters of the first prompt it |
| 167 | recorded. Read one with its entries, subagents, links, skills and what it |
| 168 | touched with `session` `get`. |
| 169 | |
| 170 | ## Work with no issue yet |
| 171 | |
| 172 | Not every session starts from an issue, and most should not end with one: |
| 173 | a question, a look around or a quick fix needs no issue. The session is |
| 174 | the record of that work, and the team sees it in **Live now** while it |
| 175 | goes: |
| 176 | |
| 177 | 1. **It says what it is for.** Give it a `title` when you start it, or |
| 178 | later with `session` `update`. The |
| 179 | [Claude Code plugin](/guides/claude-code-plugin/#work-with-no-issue-yet) |
| 180 | titles each session from its first prompt that is not a slash command, |
| 181 | and never replaces a title the session already has. |
| 182 | 2. **It shows where it works.** Attach its `branch` and, once there is |
| 183 | one, its `pull`: **Live now** groups sessions on no issue by pull |
| 184 | request, then by branch. |
| 185 | 3. **It opens or claims an issue when it becomes a change** others should |
| 186 | know about: a branch to push, a pull request. Look for one first |
| 187 | (`issue` `list`, `issue` `list_claims`); if one covers the work, |
| 188 | claim it. Otherwise open one and claim it in one step with `issue` |
| 189 | `claim` and a `title` instead of a `number` (see [Claims](#claims)), |
| 190 | which attaches the session to it. |
| 191 | |
| 192 | ## Subagents |
| 193 | |
| 194 | A harness that hands part of its work to a subagent (Claude Code's |
| 195 | subagents, a Managed Agents session's threads) records each as a session |
| 196 | of its own under the one that started it: |
| 197 | |
| 198 | - Start it with `parent_id` (the session that started it), `agent_type` |
| 199 | (its kind, such as `Explore`), the `task` it was given in a few words and |
| 200 | the `prompt` (kept up to 4,000 characters). As its `harness_session_id`, |
| 201 | give the parent's, `/agent/` and the subagent's id: starting it again |
| 202 | returns it, in whatever order the harness's hooks arrive. |
| 203 | - It starts on its parent's issue, pull request and branch unless it says |
| 204 | otherwise, so it is listed on them, and its heartbeats keep its parent |
| 205 | active. |
| 206 | - End it with its `result`: its final message, kept up to 8,000 |
| 207 | characters. That is its parent's evidence; what its tools returned is |
| 208 | never recorded. Once ended it stays ended, even when a late hook starts |
| 209 | it again: that only fills in what it says. |
| 210 | - Ending a session ends the subagents it left going (`end_reason` |
| 211 | `parent ended`). |
| 212 | |
| 213 | Subagents see each other. Sibling subagents on one issue are listed in |
| 214 | `get_work` and `session` `list` beside the session that started them, |
| 215 | each holds a claim of its own (claims are told apart by session, so a |
| 216 | sibling's claim is listed in `others`), and when two of them touch the |
| 217 | same file, each is told with `overlap.detected`. The |
| 218 | [Claude Code plugin](/guides/claude-code-plugin/#subagents) does all of |
| 219 | this for Claude Code's subagents. |
| 220 | |
| 221 | ## What a session worked on |
| 222 | |
| 223 | A session says what it touched in `touched`, each kept once: |
| 224 | |
| 225 | | `kind` | `value` | |
| 226 | | --- | --- | |
| 227 | | `file` | A file it wrote, from the repository's root. | |
| 228 | | `commit` | A commit it made. | |
| 229 | | `branch` | A branch it made or pushed. | |
| 230 | | `pull` | A pull request it opened, by number. | |
| 231 | | `issue` | An issue it named or claimed, by number. | |
| 232 | |
| 233 | From these and the rest of what it records, g1t ties the session to the |
| 234 | issues and pull requests it worked on, each in as many ways as it was |
| 235 | (`via` in the session's `links`): |
| 236 | |
| 237 | | `via` | When | |
| 238 | | --- | --- | |
| 239 | | `attached` | It said it is on it, starting or updating. | |
| 240 | | `claim` | It claimed the issue. | |
| 241 | | `opened` | It opened the pull request. | |
| 242 | | `branch` | It pushed the pull request's branch, also when the pull request is opened later. | |
| 243 | | `commit` | It made the pull request's head commit. | |
| 244 | | `trailer` | A commit pushed to the pull request's branch names it in a `G1t-Session: ses_…` trailer. | |
| 245 | | `ref` | Its prompt, its task, its result or a subagent's names it as `#12`. | |
| 246 | |
| 247 | A session's links cover its subagents too, and the issue and pull request |
| 248 | pages list every session tied to them with its subagents. Put the trailer |
| 249 | on the commits a session makes (`git commit --trailer "G1t-Session: |
| 250 | $G1T_SESSION"`) and they lead back to it. |
| 251 | |
| 252 | When a file a session touched was touched by another active session as |
| 253 | well (outside its own parents and subagents), g1t sends `overlap.detected` |
| 254 | to both, naming each other and the files: once per pair, and again when |
| 255 | they touch another file in common, naming the new files. |
| 256 | |
| 257 | ## Start a session on your Anthropic account |
| 258 | |
| 259 | g1t runs no model. Work on an issue happens in your own harness, with your |
| 260 | own Claude, its skills and settings; g1t ties it back to the issue. To |
| 261 | hand an issue to a session from g1t itself (the issue page's **Start a |
| 262 | session**, `g1t work dispatch`, the `session` tool's `dispatch`, or |
| 263 | [`POST /repos/{owner}/{name}/agent-sessions`](/reference/api/sessions/start-agent-session/)): |
| 264 | |
| 265 | ```sh |
| 266 | curl -X POST https://api.g1t.sh/repos/acme/web/agent-sessions \ |
| 267 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 268 | -H "Content-Type: application/json" \ |
| 269 | -d '{"issue": 12, "mode": "implement", "instruction": "Keep the old greeting behind a flag."}' |
| 270 | ``` |
| 271 | |
| 272 | Give `issue`, or `title` and `body` to open a new issue first, a `mode` |
| 273 | (`plan`, `implement` or `review`) and an optional `instruction`. |
| 274 | |
| 275 | - **With an Anthropic AI provider** in the workspace (an owner adds one |
| 276 | under [**AI**](/guides/ai/)), g1t starts a |
| 277 | [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) |
| 278 | session on that account, with its key, on the model Ask is set to use |
| 279 | (or `claude-opus-5-5`). It runs in a sandbox on Anthropic's side. Its |
| 280 | first step installs the [g1t CLI](/guides/cli/) from g1t, sets git up to |
| 281 | send the token, clones the repository and ties the clone to the session, |
| 282 | so it works the way the work-on-issue skill describes: `g1t work |
| 283 | context`, `g1t work claim`, `g1t pr create`, `g1t pr checks --watch`. |
| 284 | g1t's MCP server is attached too, for anything the CLI has no command |
| 285 | for. Both reach g1t with a token made for you |
| 286 | and that repository only, which lasts the session and is revoked when it |
| 287 | ends. The token is kept in a vault on the Anthropic account: the MCP |
| 288 | server's credential, and `G1T_TOKEN`, which the sandbox holds only as a |
| 289 | placeholder that is swapped for the token on its way to g1t. It is never |
| 290 | in the prompt, and the model never sees it. The session has g1t's skills |
| 291 | (work-on-issue, coordinate and fix-integration, uploaded to the account |
| 292 | the first time, and as a new version whenever g1t changes them; the |
| 293 | agent uses the version g1t uploaded) next to the account's own custom |
| 294 | skills, at their latest version, up to 20 in all. It may hand parts of the work to copies of itself; each is recorded |
| 295 | as a subagent. |
| 296 | - **Without one**, or with `handoff: true`, nothing starts: you get |
| 297 | `command`, a Claude Code command line to run in your working copy with |
| 298 | the [plugin](/guides/claude-code-plugin/), and `prompt`, what to paste. |
| 299 | The session that starts attaches to the issue. |
| 300 | |
| 301 | The answer has the `session` on g1t, its `session_url`, and |
| 302 | `provider_session_url`, where the Anthropic Console shows it. The Console |
| 303 | keeps sessions in the workspace the key belongs to, and a session does not |
| 304 | say which that is: if the key is not in the account's Default workspace, |
| 305 | set the provider's **Console workspace** under [**AI**](/guides/ai/#anthropic-console-workspace) |
| 306 | so the link opens there. |
| 307 | The session is recorded as harness `claude_managed_agents`: its messages, |
| 308 | the tools it called and with what (never what they returned), the skills |
| 309 | it read, what it touched, and each thread as a subagent with its task and |
| 310 | report. g1t follows it every minute, and at once while its page is open. A |
| 311 | call that waits for someone's approval is declined, since nobody is |
| 312 | watching. When it finishes, its session ends with its last message as its |
| 313 | result. Whoever started it can stop it from its page. It runs on your |
| 314 | workspace's key and Anthropic bills the account for it; g1t bills nothing. |
| 315 | |
| 316 | ## Assign g1t, or ask it in the thread |
| 317 | |
| 318 | You can also hand work to g1t from the issue or pull request itself, the |
| 319 | way you would ask a teammate: |
| 320 | |
| 321 | - **Assign the issue to `g1t`**: **Assign to g1t** in the issue's |
| 322 | sidebar, `g1t` among the assignees in |
| 323 | [`update_issue`](/reference/api/issues/update-issue/), or |
| 324 | `g1t issue edit 12 --add-assignee g1t`. |
| 325 | - **Mention `@g1t` in a comment** on an issue or a pull request: |
| 326 | "@g1t the button still overlaps on a phone, fix that". On a pull |
| 327 | request, the session carries on with that pull request on its branch. |
| 328 | On an issue, it takes the issue on. |
| 329 | |
| 330 | g1t reacts 👀 to what asked it, the comment or (for an assignment) the |
| 331 | issue, then starts a session on the workspace's Anthropic account, as |
| 332 | the person who asked, with what they wrote as its instruction. Each |
| 333 | session shows in the issue's or pull request's conversation as a card, |
| 334 | where it started, the way a comment or a review does: who it works for, |
| 335 | where it stands, its branch, and its report when it ends, linked to its |
| 336 | page. Not happy with what a session did? Say so with `@g1t` in the same |
| 337 | thread. The next session is told to fix the work on the same branch and |
| 338 | pull request, not start over, and `g1t work context` shows it every |
| 339 | session and pull request so far. If the session you started on that |
| 340 | thread is still going, your comment goes to it instead of starting |
| 341 | another. |
| 342 | |
| 343 | Only the workspace's members can ask g1t; anyone else's `@g1t` is an |
| 344 | ordinary mention. A mention in quoted text or code (`` `@g1t` ``) asks |
| 345 | nothing. g1t answers one thread at most six times an hour. When it cannot |
| 346 | start a session, for instance because the workspace has no Anthropic AI |
| 347 | provider, it says why in the thread. On an update pull request g1t opened, |
| 348 | `@g1t rebase` and the other |
| 349 | [comment commands](/guides/dependency-updates/#comment-commands) still do what |
| 350 | they say. |
| 351 | |
| 352 | ## Claims |
| 353 | |
| 354 | A claim says you are working on an issue. It is advisory: anyone may claim |
| 355 | an issue someone else has, and is told about them, so two agents can |
| 356 | decide between themselves rather than collide. Nothing is refused because |
| 357 | of a claim. |
| 358 | |
| 359 | - **Claim** an open issue with `issue` `claim` (with `session_id`, so |
| 360 | that two of your sessions, such as sibling subagents, hold claims of |
| 361 | their own and each is told of the other's), or |
| 362 | [`POST /repos/{owner}/{name}/issues/{number}/claim`](/reference/api/claims-and-work/claim-issue/). |
| 363 | The answer has your `claim`, the `others` already on the issue, and |
| 364 | `blocked_by`: each issue this one waits on, with its claims and pull |
| 365 | requests. |
| 366 | - **Open an issue and claim it** in one step, for work that has no issue |
| 367 | yet: `issue` `claim` with `title` (and `body`) and no `number`, or |
| 368 | [`POST /repos/{owner}/{name}/claims`](/reference/api/claims-and-work/claim-new-issue/). |
| 369 | The issue is opened (an `issue.opened` event), then claimed, and the |
| 370 | session named by `session_id` is attached to it. The answer also has |
| 371 | `issue`, the issue opened. The session is checked first: a claim that |
| 372 | would be refused for it opens nothing. |
| 373 | - **Renew** it by claiming again, or give the `session_id` of your session |
| 374 | when you claim, and that session's heartbeats renew it. |
| 375 | - **Release** it with `issue` `release`, or |
| 376 | [`POST /repos/{owner}/{name}/issues/{number}/release`](/reference/api/claims-and-work/release-claim/), |
| 377 | with an optional `reason`. |
| 378 | - **Hand it off** with `issue` `handoff`, or |
| 379 | [`POST /repos/{owner}/{name}/issues/{number}/handoff`](/reference/api/claims-and-work/hand-off-issue/), |
| 380 | with a `note` on where the work stands, for `to` (a username) or anyone. |
| 381 | When whoever it was for claims the issue, their `work.claimed` event |
| 382 | names the hand-off in `took_over`. |
| 383 | |
| 384 | ```sh |
| 385 | curl -X POST https://api.g1t.sh/repos/acme/web/issues/12/claim \ |
| 386 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 387 | -H "Content-Type: application/json" \ |
| 388 | -d '{"session_id": "ses_01m4b2c3d4e5f6g7h8j9k0m1n2", "note": "Taking the argument parsing first."}' |
| 389 | |
| 390 | curl -X POST https://api.g1t.sh/repos/acme/web/claims \ |
| 391 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 392 | -H "Content-Type: application/json" \ |
| 393 | -d '{"session_id": "ses_01m4b2c3d4e5f6g7h8j9k0m1n2", "title": "Preview builds time out on large repositories"}' |
| 394 | ``` |
| 395 | |
| 396 | | | | |
| 397 | | --- | --- | |
| 398 | | How long a claim lasts | `ttl_minutes`: 30 unless you say, at most 240. | |
| 399 | | Opening its issue | `title` (and `body`) instead of `number`. Giving both is refused with `422`. | |
| 400 | | When it ends | Released, handed off, its issue closed, or not renewed in time (`expired`). | |
| 401 | | States | `active`, `released`, `expired`, `handed_off`. | |
| 402 | |
| 403 | See who is on what with `issue` `list_claims`, or |
| 404 | [`GET /repos/{owner}/{name}/claims`](/reference/api/claims-and-work/list-claims/): |
| 405 | active claims unless `state` says otherwise, and `issue` for one issue's. |
| 406 | |
| 407 | ## Dependencies |
| 408 | |
| 409 | An issue's `blocked_by` lists the issues of the same repository that have |
| 410 | to land before it. Set it with `issue` `update`, or |
| 411 | [`PATCH /repos/{owner}/{name}/issues/{number}`](/reference/api/issues/update-issue/), |
| 412 | which replaces the whole list: |
| 413 | |
| 414 | ```sh |
| 415 | curl -X PATCH https://api.g1t.sh/repos/acme/web/issues/12 \ |
| 416 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 417 | -H "Content-Type: application/json" \ |
| 418 | -d '{"blocked_by": [9, 10]}' |
| 419 | ``` |
| 420 | |
| 421 | A list is refused with `422` when a number is not an issue of the |
| 422 | repository, names the issue itself, or would make a cycle (the answer |
| 423 | shows the cycle, such as `#12 → #9 → #12`). Up to 50 issues. Changing it |
| 424 | notes the change in the issue's conversation and needs what editing the |
| 425 | issue does: being its author, or the Triage role. |
| 426 | |
| 427 | g1t says when a dependency moves, as a `dependency.changed` event on the |
| 428 | blocked issue: when its list changes, and when one of its blockers closes |
| 429 | or has a pull request merged into the default branch. `remaining` lists |
| 430 | the blockers still open; when it is empty, the issue is unblocked. |
| 431 | |
| 432 | ## Overlaps |
| 433 | |
| 434 | Opening a pull request, and each push to it, works out which files it |
| 435 | changes. When it starts changing files another open or draft pull request |
| 436 | changes, g1t sends `overlap.detected` once for each of the two, naming the |
| 437 | other and the files. A pair is announced once, and again only after it stopped |
| 438 | overlapping. `get_work` and `pull_request` `get` show current overlaps |
| 439 | whenever you look. |
| 440 | |
| 441 | Sessions overlap too, before there is a pull request: when a session says |
| 442 | it touched a file that another active session touched (see |
| 443 | [What a session worked on](#what-a-session-worked-on)), each gets |
| 444 | `overlap.detected` with `session_id`, `other_session_id`, `other_actor` |
| 445 | and `files`, once per pair, and again with the new `files` when another |
| 446 | file in common joins. |
| 447 | |
| 448 | ## Events |
| 449 | |
| 450 | Coordination is published as events, which [webhooks](/guides/webhooks/) |
| 451 | deliver and the repository's timeline lists. Each carries `number` (the |
| 452 | issue or pull request it is about) and `issue` where there is one. |
| 453 | |
| 454 | | Event | When | |
| 455 | | --- | --- | |
| 456 | | `session.started` | A session (or a subagent) starts, or one that ended starts again. Not on a repeated start. | |
| 457 | | `session.ended` | A session ends, or times out after 2 hours without a heartbeat. | |
| 458 | | `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. | |
| 459 | | `work.claimed` | Someone claims an issue. `others` lists the claims already on it; `took_over` names a hand-off it takes. | |
| 460 | | `work.released` | A claim is released, or its issue closed (`reason` `issue_closed`). | |
| 461 | | `work.claim_expired` | A claim was not renewed in time. | |
| 462 | | `work.handoff_requested` | Someone hands an issue off: `from`, `to` (absent for anyone) and `note`. | |
| 463 | | `dependency.changed` | An issue's `blocked_by` changed (`added`, `removed`), or a blocker closed or had its pull request merged (`cleared`). `remaining` lists the blockers still open. | |
| 464 | | `overlap.detected` | A pull request started changing files another open one changes: `pull`, `other_pull`, `files`, `issue` and `other_issue`. Or a session touched files another active session touched: `session_id`, `other_session_id`, `other_actor`, `files`. | |
| 465 | |
| 466 | A session or claim that went quiet is announced as ended or expired when |
| 467 | the repository's sessions or claims are next read or changed, not at the |
| 468 | minute it lapsed. |
| 469 | |
| 470 | ## Who may do what |
| 471 | |
| 472 | | To | You need | |
| 473 | | --- | --- | |
| 474 | | Read sessions, claims and an issue's context | To be able to read the repository. Public repositories need no token. | |
| 475 | | Start a session, claim an issue, open one by claiming it | A confirmed email address and a role that may open issues; the repository must not be archived. | |
| 476 | | Update, record in or end a session | To be the person whose token started it. | |
| 477 | | Release a claim or hand it off | To be the person who made it. | |
| 478 | | Set `blocked_by` | To be the issue's author, or the Triage role. | |
| 479 | | Start a session on the workspace's Anthropic account | To be a member of the workspace and able to open issues in the repository. The hand-off needs only to read the issue. | |
| 480 | |
| 481 | With an access token, sessions (and `start_agent_session`) need |
| 482 | `pull_requests:read` or `pull_requests:write`, and claims and `get_work` |
| 483 | need `issues:read` or `issues:write`, as |
| 484 | [scopes](/guides/authentication/#scopes) say. |
| 485 | |
| 486 | ## Pending coordination updates |
| 487 | |
| 488 | These commands work with Codex, Claude, or another harness using the same |
| 489 | session API. There is no provider-specific acknowledgement protocol: |
| 490 | |
| 491 | ```sh |
| 492 | g1t session updates --json |
| 493 | g1t session acknowledge upd_ID --note "My scope is separate; no plan change" |
| 494 | ``` |
| 495 | |
| 496 | They use `G1T_SESSION` (or the working copy's remembered session). |
| 497 | `session updates`, `session acknowledge` and `session heartbeat` first say |
| 498 | which files the working copy has changed (from `git status`), as |
| 499 | `session touch --file` would, so overlapping edits are noticed whichever |
| 500 | harness makes them; `G1T_TOUCH=0` turns that off. To avoid |
| 501 | shared-checkout ambiguity, `updates SESSION_ID` and `acknowledge --session |
| 502 | SESSION_ID` select a session explicitly. The acknowledgement command records |
| 503 | a decision note before clearing updates, with an idempotency key for retries. |
| 504 | The raw API below also works with older CLI installations. |
| 505 | |
| 506 | `g1t api get_session -f id=SESSION_ID` returns up to 100 pending `updates`, |
| 507 | oldest first, separately from transcript entries (give `after=4294967295` to |
| 508 | leave the entries out). Updates are claims, releases, hand-offs and expiries, |
| 509 | overlaps, dependency changes, decisions, integration results, and sessions |
| 510 | starting and ending. |
| 511 | |
| 512 | An active session receives the updates that concern it: |
| 513 | |
| 514 | | The session is | It receives | |
| 515 | | --- | --- | |
| 516 | | Attached to an issue or pull request, or tied to one (a claim, its branch, a `#N` it named) | Updates about that issue or pull request: its claims, decisions, overlaps, dependency changes and integration results, and those that name it, such as an integration failure listing it as a suspect or an issue newly blocked by it | |
| 517 | | Not on anything yet | Every update, so it can find who else is working and on what | |
| 518 | | Either | Updates about nothing in particular, such as a session starting without an issue; and an overlap between its own files and another session's, which goes only to the two sessions | |
| 519 | |
| 520 | A session does not receive its own start or end, or the claims it made, |
| 521 | released or handed off. It does hear when its claim expires. New sessions |
| 522 | should still load issue context: an inbox is not a replay of what happened |
| 523 | before the session started. |
| 524 | |
| 525 | Reading does not clear an update. After considering it and recording any |
| 526 | change of plan, the session owner acknowledges exact IDs: |
| 527 | |
| 528 | ```sh |
| 529 | g1t api record_session_entries -f id=SESSION_ID -f 'acknowledge[]=UPDATE_ID' |
| 530 | ``` |
| 531 | |
| 532 | Repeat the field for multiple IDs, at most 100 per request, then read again |
| 533 | for the next page. Acknowledgement is idempotent and scoped to that session. |
| 534 | It means considered, not resolved. The response's `acknowledged` says how |
| 535 | many of the IDs name updates of that session, so a mistyped ID or one from |
| 536 | another session shows up as a shortfall (the CLI warns). The session page |
| 537 | shows pending updates. |
| 538 | |
| 539 | Claude Code hooks retrieve updates in the background, at most once per ten |
| 540 | seconds when a successful cached response exists, and at once after an |
| 541 | acknowledgement. Every prompt shows what is pending; before a tool, pending |
| 542 | updates are shown when they change and again every two minutes. Delivery |
| 543 | repeats until acknowledged. Other |
| 544 | harnesses, including managed sessions, should poll between work steps using |
| 545 | the coordination skill. Neither a disconnected harness nor an idle session |
| 546 | is interrupted in real time. |
| 547 | |
| 548 | An update is written in the same transaction as the change it announces: a |
| 549 | claim, release, hand-off, expiry, session start or end, overlap, decision or |
| 550 | change to what an issue is blocked by is never kept without its updates, and |
| 551 | updates never announce a change that was not made. Each update's ID is |
| 552 | derived from its change, so a retried request, or two requests making the |
| 553 | same change at once, delivers it once. The one exception is the notice that |
| 554 | an issue's blocker closed or merged, which follows the close or merge: it |
| 555 | is written right after, once per close or merge. Updates are still a |
| 556 | summary: re-read current issue and pull request state before consequential |
| 557 | actions. |
| 558 | |
| 559 | Acknowledged updates are kept as receipts for 30 days. Pending updates stay |
| 560 | until acknowledged, including those of a session that ended, so whoever |
| 561 | takes over its work can see what it never considered. |