# Agent: GitHub

**Page:** api/agent/github

[Download Raw Markdown](./api/agent/github.md)

---

{/* AUTO-GENERATED — Do not edit manually. Regenerate with: npm run docs:api:generate */}



The Agent: GitHub endpoints expose GitHub authentication (device flow and PAT), repository browsing (repos, branches, working-tree status), and repository mutations (clone, commit, sync, pull request). Authentication state is process-wide, while repo/cwd-scoped operations resolve against the per-request `X-Hoody-Cwd` header. The token is never returned over the wire.


Every write operation runs through a hardened argv builder with the token only in the environment. The HTTP edge has no service-level auth — `hoody-proxy` is the boundary (network-position trust).


## Authentication

### `GET /api/v1/agent/github/auth/status`

Reports the process-wide GitHub authentication state. Returns the linked account info; the token itself is never returned.



```bash
curl -X GET https://api.hoody.com/api/v1/agent/github/auth/status
```


```ts
const status = await client.agent.github.githubAuthStatus();
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope (the .hoody project layer / record cwd / tool+workflow cwd). |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override selecting which on-disk .hoody install a stateless read/write resolves. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension. |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector (`"global"` or a 24-hex id). Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header (read only when the header is absent). |

#### Responses



```json
{
  "authenticated": true,
  "login": "octocat",
  "host": "github.com",
  "scopes": ["repo", "workflow"]
}
```


```json
{
  "code": "realm_scope_unsupported",
  "message": "realm scope not supported on this route"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy; its source IP is private/local. | Reach the agent through hoody-proxy (e.g. `hoody agent …` → platform → proxy). |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request (busy or per-client stream concurrency cap). | Honor `Retry-After` and retry. |



---

### `POST /api/v1/agent/github/auth/login`

Begins a GitHub login. With no body `token`, starts the device flow and returns the non-secret verification fields. With a body `token` (a PAT), validates and persists the token directly without a device flow. For GitHub Enterprise, set body `host` (default `github.com`).



```bash
# Device flow (no body)
curl -X POST https://api.hoody.com/api/v1/agent/github/auth/login

# PAT
curl -X POST https://api.hoody.com/api/v1/agent/github/auth/login \
  -H "Content-Type: application/json" \
  -d '{"token": "ghp_xxxxxxxxxxxxxxxxxxxx"}'

# GitHub Enterprise
curl -X POST https://api.hoody.com/api/v1/agent/github/auth/login \
  -H "Content-Type: application/json" \
  -d '{"host": "github.acme.internal"}'
```


```ts
// Device flow
await client.agent.github.githubLogin();

// PAT
await client.agent.github.githubLogin({
  data: { token: "ghp_xxxxxxxxxxxxxxxxxxxx" }
});
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Request Body

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `token` | string | No | Optional PAT. When present, the login validates and persists this token (no device flow). Kept in env, never returned. |
| `host` | string | No | GitHub host for GitHub Enterprise (GHES); defaults to `github.com`. Must match the host on the subsequent poll call. |

#### Responses



Device flow started (non-secret verification fields) OR PAT linked.
```json
{
  "device_code": "3584d83530557fdd1f46af8289938c8ef79f9dc5",
  "user_code": "WDJB-MJHT",
  "verification_uri": "https://github.com/login/device",
  "interval": 5,
  "expires_in": 900
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "admin_unauthorized",
  "message": "memory administration requires a valid admin token"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket memAdminGate / systemAdminGate refused the request. | Run the daemon with socket auth and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap (`MaxBodyBytes`, default 8 MiB). | Reduce the request body below the configured limit; split a large payload into smaller requests. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

### `POST /api/v1/agent/github/auth/login/poll`

Polls an in-flight GitHub device-flow login to completion. Forward the `{device_code, interval, expires_in}` the start reply returned. Required to complete a device-flow login over HTTP — the start RPC only returns the verification URL and device code.



```bash
curl -X POST https://api.hoody.com/api/v1/agent/github/auth/login/poll \
  -H "Content-Type: application/json" \
  -d '{
    "device_code": "3584d83530557fdd1f46af8289938c8ef79f9dc5",
    "interval": 5,
    "expires_in": 900
  }'
```


```ts
await client.agent.github.githubLoginPoll({
  data: {
    device_code: "3584d83530557fdd1f46af8289938c8ef79f9dc5",
    interval: 5,
    expires_in: 900
  }
});
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Request Body

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `device_code` | string | Yes | The `device_code` returned by `POST /github/auth/login`. |
| `host` | string | No | The GitHub host (default `github.com`); must match the start call. |
| `interval` | integer | No | The poll interval (seconds) the start reply returned. |
| `expires_in` | integer | No | The device-code lifetime (seconds) the start reply returned. |

#### Responses



Login completed; the token is persisted (never returned).
```json
{
  "key": "github:default",
  "login": "octocat",
  "host": "github.com"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket memAdminGate / systemAdminGate refused the request. | Run the daemon with socket auth and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap. | Reduce the request body below the configured limit; split a large payload into smaller requests. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

## Read operations

### `GET /api/v1/agent/github/repos`

Lists known/configured repositories (`github.repo.list`).



```bash
curl -X GET "https://api.hoody.com/api/v1/agent/github/repos?page=1&limit=20"
```


```ts
const repos = await client.agent.github.githubReposIterator({
  page: 1,
  limit: 20
});
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `page` | query | integer | No | 1-based page number for pagination. |
| `limit` | query | integer | No | Maximum items per page (`0` = no pagination). |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Responses



```json
{
  "items": [
    {
      "full_name": "octocat/Hello-World",
      "clone_url": "https://github.com/octocat/Hello-World.git",
      "default_branch": "main",
      "private": false
    }
  ],
  "meta": {
    "total": 42,
    "page": 1,
    "limit": 20
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

### `GET /api/v1/agent/github/branches`

Lists branches for the requesting cwd's repository (`github.branch.list`). Cwd-scoped, not realm-scoped.



```bash
curl -X GET "https://api.hoody.com/api/v1/agent/github/branches?page=1&limit=20"
```


```ts
const branches = await client.agent.github.githubBranchesIterator({
  page: 1,
  limit: 20
});
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `page` | query | integer | No | 1-based page number for pagination. |
| `limit` | query | integer | No | Maximum items per page (`0` = no pagination). |
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Responses



```json
{
  "items": [
    {
      "name": "main",
      "sha": "c3d0be41ecbe669545ee3e94d31ed9a4bc91ee3c",
      "protected": true
    },
    {
      "name": "feature/login",
      "sha": "a1b2c3d4e5f6789012345678901234567890abcd",
      "protected": false
    }
  ],
  "meta": {
    "total": 14,
    "page": 1,
    "limit": 20
  }
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

### `GET /api/v1/agent/github/status`

Returns the git working-tree status (`github.status`) for the requesting cwd. Cwd-scoped (git is repo/cwd-relative), not realm-scoped.



```bash
curl -X GET https://api.hoody.com/api/v1/agent/github/status
```


```ts
const status = await client.agent.github.githubStatus();
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Responses



```json
{
  "branch": "main",
  "clean": false,
  "staged": [
    { "path": "src/api.ts", "status": "modified" }
  ],
  "unstaged": [
    { "path": "README.md", "status": "modified" }
  ],
  "untracked": [
    { "path": "src/new-feature.ts" }
  ],
  "ahead": 1,
  "behind": 0
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

## Write operations

### `POST /api/v1/agent/github/clone`

Clones a GitHub repository through the hardened argv builder (token only in env, cwd-scoped). Supply either `repo` (`owner/name` or an https GitHub URL) or the canonical `full_name` + `clone_url` pair. The clone runs against the active account host — a URL whose host does not match is rejected. Destructive.



```bash
curl -X POST https://api.hoody.com/api/v1/agent/github/clone \
  -H "Content-Type: application/json" \
  -d '{
    "repo": "octocat/Hello-World",
    "shallow": true
  }'
```


```ts
await client.agent.github.githubClone({
  data: {
    repo: "octocat/Hello-World",
    shallow: true
  }
});
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Request Body

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `repo` | string | No | The repository to clone: `"owner/name"` or an https GitHub URL. Translated to `full_name` + `clone_url` against the active account host. |
| `dir` | string | No | Optional managed clone root override (`clone_root`); the traversal-safe parent/dest are derived under it. |
| `full_name` | string | No | Canonical `"owner/name"` (alternative to `repo`; used as-is when supplied). Requires `clone_url`. |
| `clone_url` | string | No | Canonical https clone URL (alternative to `repo`; re-validated against the active account host). Requires `full_name`. |
| `shallow` | boolean | No | Shallow clone (default `true`). |


A request with NEITHER `repo` NOR the canonical `full_name`+`clone_url` pair is rejected. If BOTH are supplied, the explicit `full_name`/`clone_url` WIN and `repo` only fills a missing one.


#### Responses



```json
{
  "full_name": "octocat/Hello-World",
  "path": "/var/lib/hoody/repos/octocat/Hello-World",
  "shallow": true
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket memAdminGate / systemAdminGate refused the request. | Run the daemon with socket auth and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap. | Reduce the request body below the configured limit; split a large payload into smaller requests. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

### `POST /api/v1/agent/github/commit`

Stages all changes and commits in the requesting cwd's repository (`github.commit`) through the hardened argv builder, cwd-scoped. Destructive.



```bash
curl -X POST https://api.hoody.com/api/v1/agent/github/commit \
  -H "Content-Type: application/json" \
  -d '{"message": "feat: add new API endpoint"}'
```


```ts
await client.agent.github.githubCommit({
  data: { message: "feat: add new API endpoint" }
});
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Request Body

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `message` | string | Yes | The commit message. |

#### Responses



```json
{
  "sha": "a1b2c3d4e5f6789012345678901234567890abcd",
  "branch": "main",
  "message": "feat: add new API endpoint",
  "files_changed": 3
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket memAdminGate / systemAdminGate refused the request. | Run the daemon with socket auth and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap. | Reduce the request body below the configured limit; split a large payload into smaller requests. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

### `POST /api/v1/agent/github/sync`

Runs `fetch → pull → push` as one logical sync (`github.gw.sync`), stopping at the first non-ok step so a later push never runs against a half-synced tree. Use the body `direction` field to pull-only (`fetch+pull`) or push-only. Each step runs through the hardened argv builder with a fresh request copy. Destructive.



```bash
# Full sync
curl -X POST https://api.hoody.com/api/v1/agent/github/sync \
  -H "Content-Type: application/json" \
  -d '{}'

# Pull-only
curl -X POST https://api.hoody.com/api/v1/agent/github/sync \
  -H "Content-Type: application/json" \
  -d '{"direction": "pull"}'
```


```ts
// Full sync
await client.agent.github.githubSync();

// Pull-only
await client.agent.github.githubSync({ data: { direction: "pull" } });
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Request Body

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `direction` | string | No | Optional: `"pull"` (fetch+pull) or `"push"` (push only). Default is the full fetch→pull→push. |


`direction` is BODY-only — the shared GitHub mutator handler does not read query params, so there is no `?direction` alias.


#### Responses



```json
{
  "steps": [
    { "step": "fetch", "result": { "status": "ok" } },
    { "step": "pull", "result": { "status": "ok" } },
    { "step": "push", "result": { "status": "ok" } }
  ]
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket memAdminGate / systemAdminGate refused the request. | Run the daemon with socket auth and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap. | Reduce the request body below the configured limit; split a large payload into smaller requests. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "sync_step_failed",
  "message": "sync step failed",
  "details": {
    "failed_step": "push",
    "steps": [
      { "step": "fetch", "result": { "status": "ok" } },
      { "step": "pull", "result": { "status": "ok" } },
      { "step": "push", "result": { "status": "error", "message": "updates were rejected (non-fast-forward)" } }
    ]
  }
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `sync_step_failed` | Sync step failed | A downstream git/gh step (fetch/pull/push) failed after the sync was accepted; the steps that ran plus the failing one are returned under `details`. | Resolve the underlying git state (conflict / transport / auth) and retry the sync. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |



---

### `POST /api/v1/agent/github/pr`

Opens a pull request for the requesting cwd's repository (`github.pr.create`) through the hardened argv builder (token only in env, cwd-scoped). Destructive.



```bash
curl -X POST https://api.hoody.com/api/v1/agent/github/pr \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Add new API endpoint",
    "body": "Implements the new endpoint described in the spec.",
    "base": "main"
  }'
```


```ts
await client.agent.github.githubPullRequest({
  data: {
    title: "Add new API endpoint",
    body: "Implements the new endpoint described in the spec.",
    base: "main"
  }
});
```



#### Parameters

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `X-Hoody-Cwd` | header | string | No | Per-request working-directory scope. |
| `X-Hoody-Config-Dir` | header | string | No | Per-request `--config-dir` override. |
| `X-Hoody-Container` | header | string | No | Per-request bound remote container (omitted = local). |
| `X-Hoody-Realm` | header | string | No | Per-request realm selector. Rejected (`realm_scope_unsupported`) on this route. |
| `realm` | query | string | No | In-query alias of the `X-Hoody-Realm` header. |

#### Request Body

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `title` | string | No | The PR title. |
| `body` | string | No | The PR description. |
| `base` | string | No | Optional base branch (default the repo default). |

#### Responses



```json
{
  "url": "https://github.com/octocat/Hello-World/pull/42",
  "number": 42,
  "base": "main",
  "head": "feature/login"
}
```


```json
{
  "code": "bad_request",
  "message": "invalid request"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `bad_request` | Bad request | The request was malformed or carried invalid parameters. | Correct the request body or query parameters. |
| `realm_scope_unsupported` | Realm scope unsupported | A per-request realm header was supplied to a route with no realm dimension. | Omit the realm header on this route, or open a session to scope by realm. |


```json
{
  "code": "forbidden",
  "message": "request must arrive through the Hoody proxy"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `admin_unauthorized` | Rejected by the daemon's own admin gate | The daemon's Unix-socket memAdminGate / systemAdminGate refused the request. | Run the daemon with socket auth and no separate admin capability so its own gate allows HTTP requests forwarded from the gateway. |
| `forbidden` | Forbidden (not via the Hoody proxy) | The request did not arrive through hoody-proxy. | Reach the agent through hoody-proxy. |


```json
{
  "code": "not_found",
  "message": "resource not found"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `not_found` | Not found | The requested resource does not exist. | Verify the path and identifier. |


```json
{
  "code": "payload_too_large",
  "message": "request body exceeds the configured size limit"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `payload_too_large` | Payload too large | The request body exceeds the configured size cap. | Reduce the request body below the configured limit; split a large payload into smaller requests. |


```json
{
  "code": "rate_limited",
  "message": "request rate limit exceeded"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `rate_limited` | Too many requests | The per-client request rate limit was exceeded. | Honor the `Retry-After` header and retry; reduce the request rate. |


```json
{
  "code": "internal_error",
  "message": "internal server error"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `internal_error` | Internal error | An unexpected error occurred while handling the request. | Retry; if persistent, inspect the daemon logs. |


```json
{
  "code": "service_unavailable",
  "message": "service unavailable"
}
```

| Error Code | Title | Description | Resolution |
|------------|-------|-------------|------------|
| `service_unavailable` | Service unavailable | The daemon could not service the request. | Honor `Retry-After` and retry. |