Skip to content
Hoody.com

: GitHub

Authenticate to GitHub (device flow or PAT), clone repositories, stage and commit, sync (fetch/pull/push), list repos and branches, check working-tree status, and open pull requests. The token is kept in env and is never returned in any reply. Cwd-scoped reads (status, repos, branches) and the clone/commit/sync/PR mutators all operate against the working directory the requesting session is bound to via X-Hoody-Cwd. The auth routes (auth/status, auth/login, auth/login/poll, auth/active, auth/logout) have no cwd dimension.

Reports the GitHub authentication state (github.auth.status) from the account store. The token lives only in env and is never returned. This route has no realm/container/cwd/config_dir dimension, so every per-request scope header returns 400 realm_scope_unsupported.

Terminal window
curl -X GET "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/auth/status" \
-H "Authorization: Bearer <token>"
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

Begins a GitHub login. With no body token this starts a DEVICE flow and returns the non-secret {device_code, user_code, verification_uri, interval, expires_in}; the user authorizes that URL out of band, then POST /api/v1/agent/github/auth/login/poll completes the login. With a body token (a PAT) this instead validates and persists the token directly (no device flow), returning the linked {login, host}. For GitHub Enterprise (GHES) set body host (default github.com) on both the device-flow start and the PAT-add. The token lives only in env and is never returned.

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/auth/login" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{}'
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

Optional login options. Supply token to add a PAT directly; omit it to start a device flow. Supply host for GitHub Enterprise (GHES).

NameTypeRequiredDescription
tokenstringNoOptional PAT. When present the login validates + persists this token (no device flow); kept in env, never returned.
hoststringNoGitHub host for GitHub Enterprise (GHES); defaults to github.com. Must match the host on the subsequent poll call.
activatebooleanNoWhether the linked account becomes the ACTIVE one. Defaults to FALSE — linking stores the credential without changing which account is in use, because activation decides the identity your next push authenticates as. Send true when RECOVERING from an expired/revoked token: the account is linked and activated in this single call, so no follow-up githubSetActiveAccount is needed. The first account ever linked becomes active regardless, since none was. A non-boolean value is rejected.

Polls an in-flight GitHub device-flow login. Forward the {device_code, interval, expires_in} the start reply returned; the call blocks until the user authorizes (or the flow expires/cancels), then validates and persists the resulting token. Required to COMPLETE a device-flow login over HTTP (the start call only returns the verification URL / device code) — BLOCK. The token lives only in env and is never returned; only the linked {login, host} is echoed.

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/auth/login/poll" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"device_code": "3584d83530557fdd1f46af8289938c8ef79f9dc5",
"interval": 5,
"expires_in": 900
}'
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

The device-flow handle the start reply returned.

NameTypeRequiredDescription
hoststringNoThe GitHub host (default github.com); must match the start call.
device_codestringYesThe device_code returned by POST /github/auth/login.
intervalintegerNoThe poll interval (seconds) the start reply returned.
expires_inintegerNoThe device-code lifetime (seconds) the start reply returned.

Points every subsequent GitHub operation at an already-linked account. key is the account handle from githubAuthStatus’s accounts[].key ("<host>/<login>"). Use this to recover when the ACTIVE account’s token was revoked and another linked account is still good — adding a PAT activates the account it belongs to, but switching between EXISTING accounts needs this route. Returns 400 when the key names no linked account.

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/auth/active" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"key": "github.com/octocat"
}'
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

The account to activate.

NameTypeRequiredDescription
keystringYesAccount handle from githubAuthStatus accounts[].key, e.g. “github.com/octocat”.

Forgets a linked GitHub account and deletes the copies of its token that an interactive clone persisted into checkouts the daemon can currently reach. The purge is BEST-EFFORT and partial by construction — a repository in a stopped container, or one no open session is bound to, keeps its copy — so the reply carries credential_purge: "partial" and a message saying to revoke the token on GitHub for a complete removal. If the removed account was active, the active pointer moves to a remaining account (or clears).

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/auth/logout" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"key": "github.com/octocat"
}'
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

The account to remove.

NameTypeRequiredDescription
keystringYesAccount handle from githubAuthStatus accounts[].key, e.g. “github.com/octocat”.

Clones a GitHub repository. The service translates repo (owner/name OR an https github URL) into the server-authoritative {full_name, clone_url}: the clone runs against the ACTIVE account host (a URL whose host does not match is rejected), and the destination is derived traversal-safe under the managed clone root (dir overrides it). Destructive (x-cli-mode interactive).

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/clone" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"repo": "octocat/hello-world"
}'
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

The clone request. Supply EITHER repo (owner/name or an https github URL) — the service derives the canonical full_name + host-validated clone_url — OR the canonical full_name + clone_url fields directly. At least one form is required; a request with NEITHER is rejected. If BOTH are supplied the explicit full_name/clone_url WIN and repo only fills a missing one (no mutual-exclusivity error). Token rides only in env, never returned.

NameTypeRequiredDescription
repostringNoThe repository to clone: “owner/name” or an https github URL (https://<host>/<owner>/<name>[.git]). Translated to full_name + clone_url against the active account host. Supply this OR the canonical full_name+clone_url; if both, the canonical fields win.
dirstringNoOptional managed clone root override (clone_root); the traversal-safe parent/dest are derived under it.
full_namestringNoCanonical “owner/name” (alternative to repo; used as-is when supplied, taking precedence over a derived value). Requires clone_url.
clone_urlstringNoCanonical https clone URL (alternative to repo; re-validated against the active account host; takes precedence over a derived value). Requires full_name.
shallowbooleanNoShallow clone (default true).

Lists known/configured repos (github.repo.list). Returns the daemon reply verbatim ({status, repos, account}); not paginated. Cwd-scoped; a per-request realm header returns 400 realm_scope_unsupported.

Terminal window
curl -X GET "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/repos" \
-H "Authorization: Bearer <token>" \
-H "X-Hoody-Cwd: /home/user/projects/hello-world"
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

Lists branches for the requesting cwd’s repo (github.branch.list). Returns {status, branches} verbatim; not paginated. Cwd-scoped; a per-request realm header returns 400 realm_scope_unsupported.

Terminal window
curl -X GET "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/branches" \
-H "Authorization: Bearer <token>" \
-H "X-Hoody-Cwd: /home/user/projects/hello-world"
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

Returns the git working-tree status (github.status) for the requesting cwd. Cwd-scoped (git is repo/cwd-relative); a per-request realm header returns 400 realm_scope_unsupported.

Terminal window
curl -X GET "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/status" \
-H "Authorization: Bearer <token>" \
-H "X-Hoody-Cwd: /home/user/projects/hello-world"
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

Stages all changes and commits in the requesting cwd’s repo. Destructive.

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/commit" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "X-Hoody-Cwd: /home/user/projects/hello-world" \
-d '{
"message": "Fix login form validation"
}'
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

The commit request (forwarded to github.commit; cwd-scoped).

NameTypeRequiredDescription
messagestringYesThe commit message.

Runs fetchpullpush as one logical sync, stopping at the FIRST non-ok step so a later push never runs against a half-synced tree. The body direction lets a caller pull-only (fetch+pull) or push-only; default is the full sync (this is BODY-only — there is no ?direction alias). Destructive. 502 sync_step_failed carries the steps that ran plus the failing one under details.

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/sync" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "X-Hoody-Cwd: /home/user/projects/hello-world" \
-d '{}'
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

The sync request (forwarded to the service).

NameTypeRequiredDescription
directionstringNoOptional: "pull" (fetch+pull) or "push" (push only). Default is the full fetchpullpush.

Opens a pull request for the requesting cwd’s repo. Destructive.

Terminal window
curl -X POST "https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com/api/v1/agent/github/pr" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "X-Hoody-Cwd: /home/user/projects/hello-world" \
-d '{
"title": "Add install instructions",
"body": "Adds the new install steps to the README.",
"base": "main"
}'
NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd (e.g. POST /todos; createTodo also accepts a body cwd).
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves (HoodyPaths).
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: "global" or a 24-hex id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.
realmquerystringNoPer-request realm selector — the in:query alias of the X-Hoody-Realm header (read only when the header is absent): "global" or a 24-hex id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes.

The pull-request request (forwarded to github.pr.create).

NameTypeRequiredDescription
titlestringYesThe PR title (required, non-empty).
bodystringNoThe PR description.
basestringNoOptional base branch (default the repo default).