| 1 | --- |
| 2 | title: Recording sessions |
| 3 | description: How a harness records its sessions on g1t, with the API, MCP or the CLI. Start, heartbeat, record and end a session, record subagents, report what a session cost, work before there is a work item, and have g1t start sessions on your Anthropic account. |
| 4 | --- |
| 5 | |
| 6 | A [session](/work/sessions/) is one run of your harness on a repository: |
| 7 | a Claude Code session, a Codex run. This page is for whoever wires a |
| 8 | harness up to g1t: how a session is started, kept alive, recorded and |
| 9 | ended, and how its subagents are recorded. The |
| 10 | [Claude Code plugin](/guides/claude-code-plugin/) does all of it for |
| 11 | Claude Code; other harnesses call the same API. |
| 12 | |
| 13 | What sessions are for, and how the team sees them, is under Work: |
| 14 | [Sessions](/work/sessions/), [session titles](/work/session-titles/), and |
| 15 | [claims and dependencies](/work/claims-and-dependencies/), which keep |
| 16 | sessions out of each other's way. |
| 17 | |
| 18 | ## Record a session |
| 19 | |
| 20 | Start a session when the harness starts, keep it alive while it works, and |
| 21 | end it when it stops. |
| 22 | |
| 23 | 1. **Start** it with `session` `start`, `g1t session start`, or |
| 24 | [`POST /repos/{owner}/{name}/sessions`](/reference/api/sessions/start-session/), |
| 25 | naming the `harness` (`claude_code`, `codex`, `cursor`, `copilot` or |
| 26 | `other`) and the harness's own id for the session as |
| 27 | `harness_session_id`. Starting again with the same id returns the |
| 28 | session already started, so a hook can call it every time without |
| 29 | checking first. Give `item` (the work item's number in the |
| 30 | repository's workspace), `pull` and `branch` when you know them, and a |
| 31 | `title` only if you can name the whole job in a few words (up to 200 |
| 32 | characters): otherwise g1t names it (see |
| 33 | [session titles](/work/session-titles/)). |
| 34 | 2. **Heartbeat** with `session` `update`, `g1t session heartbeat`, or |
| 35 | [`PATCH /repos/{owner}/{name}/sessions/{id}`](/reference/api/sessions/update-session/) |
| 36 | with an empty body. The same call attaches the session to a work item |
| 37 | or pull request (`g1t session attach --item 12`), records the |
| 38 | `head_commit` it pushed, or names it (`title`; a title a person pinned |
| 39 | stays). A heartbeat also renews the session's claims. |
| 40 | 3. **Record** what happens with `session` `record`, or |
| 41 | [`POST /repos/{owner}/{name}/sessions/{id}/entries`](/reference/api/sessions/record-session-entries/): |
| 42 | prompts, reasoning, tool calls, notes and the skills it used (`skill`, |
| 43 | the skill's name only), up to 200 a request, and in `touched` what it |
| 44 | touched (see [what a session records](/work/sessions/#what-a-session-records)). |
| 45 | Give each entry a `key`, and recording it again does nothing. |
| 46 | 4. **End** it with `session` `end`, `g1t session end`, or |
| 47 | [`POST /repos/{owner}/{name}/sessions/{id}/end`](/reference/api/sessions/end-session/), |
| 48 | with its `result` when it has one: what it reported when it finished. |
| 49 | |
| 50 | ```sh |
| 51 | curl -X POST https://api.g1t.sh/repos/acme/web/sessions \ |
| 52 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 53 | -H "Content-Type: application/json" \ |
| 54 | -d '{"harness": "claude_code", "harness_session_id": "5b0c1f9e-3d2a-4e8b-9f61-0c7d2a9e4b13", "item": 12}' |
| 55 | ``` |
| 56 | |
| 57 | Every update and every batch of entries counts as a heartbeat. A session |
| 58 | not heard from for 15 minutes is idle, and after 30 minutes it ends as |
| 59 | timed out, until a heartbeat brings it back; see |
| 60 | [states](/work/sessions/#states). A session g1t runs on the workspace's |
| 61 | Anthropic account is recorded as harness `claude_managed_agents`. |
| 62 | |
| 63 | Entries of a session attached to a pull request show in that pull |
| 64 | request's [session](/guides/why-blame/#sessions), beside what was recorded |
| 65 | on it with `record_session`, so reviewers and why-blame see them. Entries |
| 66 | recorded before the session named its pull request move onto it when it |
| 67 | does. A session never records tool output unless you send it as a |
| 68 | `tool_result` entry. What looks like a credential is taken out of |
| 69 | everything a session records, and only the workspace's members see inside |
| 70 | a session: see [who sees what](/work/sessions/#who-sees-what). |
| 71 | |
| 72 | Updating, recording in and ending a session needs the token that started |
| 73 | it; starting one needs a confirmed email address and a role that may file |
| 74 | work items. With an access token, sessions need `pull_requests:write`. |
| 75 | See [who may do what](/work/claims-and-dependencies/#who-may-do-what). |
| 76 | |
| 77 | ## Work with no work item yet |
| 78 | |
| 79 | Not every session starts from a work item, and most should not end with |
| 80 | one: a question, a look around or a quick fix needs no work item. The |
| 81 | session is the record of that work, and the team sees it in **Live now**, |
| 82 | on **Sessions** and on the project's overview, while it goes: |
| 83 | |
| 84 | 1. **It says what it is for.** g1t names it from what it does, first |
| 85 | from its first prompt, then from its whole record (see |
| 86 | [session titles](/work/session-titles/)). Give it a `title` yourself, |
| 87 | when you start it or later with `session` `update`, only if you can |
| 88 | name the whole job. |
| 89 | 2. **It shows where it works.** Attach its `branch` and, once there is |
| 90 | one, its `pull`: the project's **Live now** groups sessions on no work |
| 91 | item by pull request, then by branch. |
| 92 | 3. **It opens or claims a work item when it becomes a change** others |
| 93 | should know about: a branch to push, a pull request. Look for one first |
| 94 | (`work_item` `list`, `work_item` `list_claims`); if one covers the work, |
| 95 | claim it. Otherwise open one and claim it in one step with `work_item` |
| 96 | `claim` and a `title` instead of a `number` (see [claims](/work/claims-and-dependencies/#claims)), |
| 97 | which attaches the session to it. |
| 98 | |
| 99 | ## Subagents |
| 100 | |
| 101 | A harness that hands part of its work to a subagent (Claude Code's |
| 102 | subagents, a Managed Agents session's threads) records each as a session |
| 103 | of its own under the one that started it: |
| 104 | |
| 105 | - Start it with `parent_id` (the session that started it), `agent_type` |
| 106 | (its kind, such as `Explore`), the `task` it was given in a few words and |
| 107 | the `prompt` (kept up to 4,000 characters). As its `harness_session_id`, |
| 108 | give the parent's, `/agent/` and the subagent's id: starting it again |
| 109 | returns it, in whatever order the harness's hooks arrive. |
| 110 | - It starts on its parent's work item, pull request and branch unless it says |
| 111 | otherwise, so it is listed on them, and its heartbeats keep its parent |
| 112 | active. |
| 113 | - End it with its `result`: its final message, kept up to 8,000 |
| 114 | characters. That is its parent's evidence; what its tools returned is |
| 115 | never recorded. Once ended it stays ended, even when a late hook starts |
| 116 | it again: that only fills in what it says. |
| 117 | - Ending a session ends the subagents it left going (`end_reason` |
| 118 | `parent ended`). |
| 119 | |
| 120 | Subagents see each other. Sibling subagents on one work item are listed in |
| 121 | `get_work` and `session` `list` beside the session that started them, |
| 122 | each holds a claim of its own (claims are told apart by session, so a |
| 123 | sibling's claim is listed in `others`), and when two of them touch the |
| 124 | same file, each is told with `overlap.detected`. The |
| 125 | [Claude Code plugin](/guides/claude-code-plugin/#subagents) does all of |
| 126 | this for Claude Code's subagents. |
| 127 | |
| 128 | ## What a session cost |
| 129 | |
| 130 | A harness can say how many tokens a session used, and g1t estimates what |
| 131 | that cost at Anthropic's list price. The session's page and the |
| 132 | workspace's **Sessions** list show it as "≈ $4.12 at list price". It is |
| 133 | an estimate, not a bill: it is what the tokens cost at Anthropic's |
| 134 | published per-token prices, whatever your plan or discounts. |
| 135 | |
| 136 | 1. **Report** the session's usage so far with `session` `update`, |
| 137 | `g1t session heartbeat --usage-json '…'`, or |
| 138 | [`PATCH /repos/{owner}/{name}/sessions/{id}`](/reference/api/sessions/update-session/) |
| 139 | with `usage`: one entry per model, with its `input_tokens`, |
| 140 | `output_tokens`, `cache_write_5m_tokens`, `cache_write_1h_tokens` and |
| 141 | `cache_read_tokens`. Usage is cumulative: each report replaces the |
| 142 | last, so send the whole session's each time. |
| 143 | |
| 144 | ```json |
| 145 | { |
| 146 | "usage": [ |
| 147 | { |
| 148 | "model": "claude-opus-5-5", |
| 149 | "input_tokens": 1840, |
| 150 | "output_tokens": 52310, |
| 151 | "cache_write_5m_tokens": 210400, |
| 152 | "cache_write_1h_tokens": 0, |
| 153 | "cache_read_tokens": 4102300 |
| 154 | } |
| 155 | ] |
| 156 | } |
| 157 | ``` |
| 158 | |
| 159 | 2. **g1t prices it** as it records it: each model's tokens at its list |
| 160 | price, cache writes at 1.25 times the input price for 5 minutes and |
| 161 | twice it for 1 hour. A model id is matched without its date |
| 162 | (`-20251001`), a `[1m]` suffix or a provider prefix |
| 163 | (`us.anthropic.`). For claude-haiku-5-5, a prompt over 100,000 tokens |
| 164 | is priced at its long-prompt rate: give those tokens in an entry of |
| 165 | their own with `tier` `long`. |
| 166 | 3. **The session shows `cost_usd`**, the sum over the models g1t has a |
| 167 | price for. A model it has no price for, another provider's included, |
| 168 | is left out, and `cost_partial` says some usage was priced as unknown |
| 169 | ("some usage priced as unknown" on the page). With no model priced, |
| 170 | `cost_usd` is null. |
| 171 | |
| 172 | A subagent reports its own usage, to its own session: its parent's |
| 173 | transcript leaves out what the subagent used, so nothing is counted twice. |
| 174 | Only the workspace's members see what a session cost, as with the rest of |
| 175 | what is inside it ([who sees what](/work/sessions/#who-sees-what)). Up to |
| 176 | 50 models a session, each count a whole number of tokens. |
| 177 | |
| 178 | The [Claude Code plugin](/guides/claude-code-plugin/#what-a-session-cost) |
| 179 | counts it from the session's transcript and sends only the counts. The |
| 180 | Codex plugin does not report usage yet: it records sessions through g1t's |
| 181 | MCP tools, with no hooks to read Codex's session files from. |
| 182 | |
| 183 | ## Start a session on your Anthropic account |
| 184 | |
| 185 | g1t runs no model. Work on a work item happens in your own harness, with |
| 186 | your own Claude, its skills and settings; g1t ties it back to the work |
| 187 | item. To hand a work item to a session from g1t itself (the work item |
| 188 | page's **Start a session**, `g1t work dispatch`, the `session` tool's |
| 189 | `dispatch`, or |
| 190 | [`POST /repos/{owner}/{name}/agent-sessions`](/reference/api/sessions/start-agent-session/), |
| 191 | in the repository the session works in): |
| 192 | |
| 193 | ```sh |
| 194 | curl -X POST https://api.g1t.sh/repos/acme/web/agent-sessions \ |
| 195 | -H "Authorization: Bearer $G1T_TOKEN" \ |
| 196 | -H "Content-Type: application/json" \ |
| 197 | -d '{"item": 12, "mode": "implement", "instruction": "Keep the old greeting behind a flag."}' |
| 198 | ``` |
| 199 | |
| 200 | Give `item`, or `title` and `body` to open a new work item first (with |
| 201 | the repository as its origin), a `mode` |
| 202 | (`plan`, `implement` or `review`) and an optional `instruction`. |
| 203 | |
| 204 | - **With an Anthropic AI provider** in the workspace (an owner adds one |
| 205 | under [**AI**](/guides/ai/)), g1t starts a |
| 206 | [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) |
| 207 | session on that account, with its key, on the model Ask is set to use |
| 208 | (or `claude-opus-5-5`). It runs in a sandbox on Anthropic's side. Its |
| 209 | first step installs the [g1t CLI](/guides/cli/) from g1t, sets git up to |
| 210 | send the token and to commit as you (your username and noreply address), |
| 211 | clones the repository and ties the clone to the session, |
| 212 | so it works the way the work-on-item skill describes: `g1t work |
| 213 | view`, `g1t work claim`, `g1t pr create --item`, `g1t pr checks --watch`. |
| 214 | It works on a branch and a pull request, except in a repository with no |
| 215 | commits yet, where there is nothing to open one against: it pushes the |
| 216 | first version straight to the default branch. To show a screenshot of its |
| 217 | preview in the pull request or a comment, it uploads the image with |
| 218 | [`g1t attach`](/guides/cli/#images-in-descriptions-and-comments) (or |
| 219 | `--attach` on `g1t pr create`, `g1t pr ready` and `g1t pr comment`) and |
| 220 | pastes the Markdown it prints, rather than committing the image. |
| 221 | g1t's MCP server is attached too, for anything the CLI has no command |
| 222 | for. Its sandbox reaches the internet as a CI runner does, and it can |
| 223 | search and read the web (web search and web fetch), for a fact the work |
| 224 | needs from outside g1t or to open its own deploy. Before a headless |
| 225 | browser (Playwright, Puppeteer) opens an https page, it copies the |
| 226 | certificates the sandbox trusts into Chromium's own store, so pages load |
| 227 | with certificate checks on. Both reach g1t with one token: g1t |
| 228 | acting on your behalf, in that repository only, which lasts the session |
| 229 | and is revoked when it ends. What the session does on g1t shows as |
| 230 | **g1t, on behalf of @you**: its comments and reviews, what it closes or |
| 231 | labels, and the work items and pull requests it opens (g1t's, requested |
| 232 | by you); the audit log says "g1t on behalf of you". What it may do is |
| 233 | your role in that repository, never more than Write, with what working on |
| 234 | a work item needs (`repo:read`, `code:write`, `work:write`, |
| 235 | `pull_requests:write`, and reading checks, workflows, deployments and |
| 236 | observability): never settings, members, secrets, webhooks or merging. |
| 237 | The session itself, its claims and its commits stay yours, and its |
| 238 | pushes are yours too: to the repository and to its pull requests' |
| 239 | working copies, under the repository's rules. An approval it gives is |
| 240 | g1t's, so it counts toward required approvals only where agents' |
| 241 | approvals do. The token is kept in a vault on the Anthropic account: the MCP |
| 242 | server's credential, and `G1T_TOKEN`, which the sandbox holds only as a |
| 243 | placeholder that is swapped for the token on its way to g1t. It is never |
| 244 | in the prompt, and the model never sees it. The session has g1t's skills |
| 245 | (work-on-item, coordinate and fix-integration, uploaded to the account |
| 246 | the first time, and as a new version whenever g1t changes them; the |
| 247 | agent uses the version g1t uploaded) next to the account's own custom |
| 248 | skills, at their latest version, up to 20 in all. It may hand parts of the work to copies of itself; each is recorded |
| 249 | as a subagent. |
| 250 | - **Without one**, or with `handoff: true`, nothing starts: you get |
| 251 | `command`, a Claude Code command line to run in your working copy with |
| 252 | the [plugin](/guides/claude-code-plugin/), and `prompt`, what to paste. |
| 253 | The session that starts attaches to the work item. |
| 254 | |
| 255 | The answer has the `session` on g1t, its `session_url`, and |
| 256 | `provider_session_url`, where the Anthropic Console shows it. The Console |
| 257 | keeps sessions in the workspace the key belongs to, and a session does not |
| 258 | say which that is: if the key is not in the account's Default workspace, |
| 259 | set the provider's **Console workspace** under [**AI**](/guides/ai/#anthropic-console-workspace) |
| 260 | so the link opens there. |
| 261 | The session is recorded as harness `claude_managed_agents`: its messages, |
| 262 | the tools it called and with what (never what they returned), the skills |
| 263 | it read, what it touched, and each thread as a subagent with its task and |
| 264 | report. g1t follows it every minute, and at once while its page is open. A |
| 265 | call that waits for someone's approval is declined, since nobody is |
| 266 | watching. When it finishes, its session ends with its last message as its |
| 267 | result. Whoever started it can stop it from its page, and open it on the |
| 268 | Claude Console from there (**Open in Claude Console**); nobody else is |
| 269 | given that link, since the Console shows everything the session was asked |
| 270 | and every tool's output. It runs on your |
| 271 | workspace's key and Anthropic bills the account for it; g1t bills nothing. |
| 272 | |
| 273 | ## Assign g1t, or ask it in the thread |
| 274 | |
| 275 | You can also hand work to g1t from the work item or pull request itself, |
| 276 | the way you would ask a teammate: |
| 277 | |
| 278 | - **Assign the work item to `g1t`**: **Assign to g1t** in the work |
| 279 | item's sidebar, `g1t` among the assignees in |
| 280 | [`update_work_item`](/reference/api/work-items/update-work-item/), or |
| 281 | `g1t work edit 12 --add-assignee g1t`. |
| 282 | - **Mention `@g1t` in a comment** on a work item or a pull request: |
| 283 | "@g1t the button still overlaps on a phone, fix that". On a pull |
| 284 | request, the session carries on with that pull request on its branch. |
| 285 | On a work item, it takes the work item on. |
| 286 | |
| 287 | g1t reacts 👀 to what asked it, the comment or (for an assignment) the |
| 288 | work item, then starts a session on the workspace's Anthropic account, as |
| 289 | the person who asked, with what they wrote as its instruction. Each |
| 290 | session shows in the work item's or pull request's conversation as a card, |
| 291 | where it started, the way a comment or a review does: who it works for, |
| 292 | where it stands, its branch, and its report when it ends, linked to its |
| 293 | page. Not happy with what a session did? Say so with `@g1t` in the same |
| 294 | thread. The next session is told to fix the work on the same branch and |
| 295 | pull request, not start over, and `g1t work view` shows it every |
| 296 | session and pull request so far. If the session you started on that |
| 297 | thread is still going, your comment goes to it instead of starting |
| 298 | another. |
| 299 | |
| 300 | Only the workspace's members can ask g1t; anyone else's `@g1t` is an |
| 301 | ordinary mention. A mention in quoted text or code (`` `@g1t` ``) asks |
| 302 | nothing. g1t answers one thread at most six times an hour. When it cannot |
| 303 | start a session, for instance because the workspace has no Anthropic AI |
| 304 | provider, it says why in the thread. On an update pull request g1t opened, |
| 305 | `@g1t rebase` and the other |
| 306 | [comment commands](/guides/dependency-updates/#comment-commands) still do what |
| 307 | they say. |