Octopool CLI
The octopool Go CLI is the product entrypoint. It logs in against the relay, stores a caller token locally, and acts as a drop-in gh shim for the read-only GitHub commands Octopool supports — falling through to the real gh for everything else.
Source: cmd/octopool/.
The compiled-in default endpoint is https://octopool.dev. No config is required for normal OpenClaw use, and self-hosted servers are selected at login time.
#Install modes
Install with Homebrew:
brew install openclaw/tap/octopool
Or install from source:
go install github.com/openclaw/octopool/cmd/octopool@latest
The binary inspects argv[0] and behaves as a gh shim when invoked as gh or octopool-gh:
octopool gh ...— explicit subcommand.- symlink
octopoolasgh— transparent shim onPATH. - symlink
octopoolasoctopool-gh— side-by-side shim.
#octopool install-shim [--shell zsh] [--dry-run]
Installs the transparent gh shim for interactive, login, and non-interactive zsh processes. The command:
- resolves and pins the real GitHub CLI as
OCTOPOOL_GH_PATH, preventing fallback loops; - creates an isolated
ghsymlink under$XDG_DATA_HOME/octopool/bin(or~/.local/share/octopool/bin); - adds or replaces a clearly marked managed block in
$ZDOTDIR/.zshenv(or~/.zshenv) so the shim directory stays first onPATH; and - verifies the result with a non-interactive
zsh -cprocess.
Re-running the command is idempotent. Existing shell configuration outside the managed block is preserved. --dry-run validates the plan and prints its paths without writing. Only zsh is currently supported because it has a startup file that every interactive and non-interactive invocation reads.
octopool install-shim --dry-run
octopool install-shim
zsh -c 'command -v gh'
#Commands
#octopool login [server]
Reads a local GitHub token (GH_TOKEN, GITHUB_TOKEN, or gh auth token), exchanges it with POST /v1/login/github-cli, and saves the returned caller token. The server can be passed as a positional argument, --server, or the older --url flag:
octopool login
octopool login https://octopool.your-org.dev
octopool login --server https://octopool.your-org.dev
- If
gh auth tokenfails, the CLI prints the exact real-ghweb reauthentication and Octopool retry commands instead of returning only the subprocess exit status. - The login URL must be HTTPS.
http://is allowed only for loopback hosts, or whenOCTOPOOL_ALLOW_INSECURE_LOGIN=1is set for local development. - The CLI fetches
GET /.well-known/octopool, verifiesservice: "octopool", uses the discoveredapi_base, and defaults to the discovereddefault_poolunless--poolis passed. - If discovery points
api_baseat a different host, login fails unless--trust-discovery-redirectis passed. This keeps a mistyped or compromised discovery host from silently receiving your local GitHub token. - The token is stored 0600 at
<user-config-dir>/octopool/auth.json(URL, pool, token, login, timestamp). - Octopool validates the GitHub identity and OpenClaw org membership during login, and binds the caller by immutable GitHub user id. See Auth.
- Verified members of
ALLOWED_GITHUB_ORGself-enroll intoDEFAULT_LOGIN_POOL. Admin provisioning remains available for non-default pools and manual token issuance.
octopool login
# logged in to https://octopool.dev as steipete for pool maintainers
#octopool whoami [--json]
Prints the saved login target:
octopool whoami
# server: https://octopool.dev
# pool: maintainers
# login: steipete
Use --json for scripts.
#octopool gh api <GET path> [--jq <expr>]
Relays a read-only gh api call through Octopool's cache and pool. Prints the GitHub response body exactly like gh api, optionally piping it through jq -r <expr>.
octopool gh api repos/openclaw/openclaw/pulls/85341 --jq .number
# 85341
#octopool gh pr|issue|run|repo|release ...
The shim also handles common top-level GitHub CLI read commands by translating them to safe relay routes:
octopool gh pr view 85341 -R openclaw/openclaw --json number,title,url
octopool gh pr view 85341 -R openclaw/openclaw --json number,files,commits,comments,reviews
octopool gh pr list -R openclaw/openclaw --state open --limit 20 --json number,title,url
octopool gh pr diff 85341 -R openclaw/openclaw --patch
octopool gh pr checks 85341 -R openclaw/openclaw --json name,state,bucket,link,workflow
octopool gh search issues cache regression -R openclaw/openclaw --state open --json number,title,url
octopool gh search prs rate limit -R openclaw/openclaw --state open --json number,title,url
octopool gh issue view 80490 -R openclaw/openclaw --json number,title,state,url
octopool gh issue list -R openclaw/openclaw --state open --label bug --limit 20 --json number,title,url
octopool gh run list -R openclaw/openclaw --branch main --limit 10 --json databaseId,workflowName,status,conclusion,url
octopool gh run view 26360397003 -R openclaw/openclaw --json databaseId,workflowName,status,conclusion,url
octopool gh run view 26360397003 -R openclaw/openclaw --json status,conclusion,jobs
octopool gh repo view openclaw/openclaw --json nameWithOwner,defaultBranchRef,url
octopool gh workflow list -R openclaw/octopool --json id,name,path,state
octopool gh workflow view ci.yml -R openclaw/octopool --json id,name,path,state
octopool gh label list -R openclaw/octopool --json name,color,description
octopool gh gist view abc123 --json id,url,isPublic
octopool gh search repos octopool relay --json name,nameWithOwner,url
octopool gh release list -R openclaw/octopool --limit 10 --json tagName,name,url
octopool gh release view v0.3.0 -R openclaw/octopool --json tagName,name,url
octopool gh api repos/openclaw/octopool/contents/README.md?ref=main --jq .content
Top-level commands are relayed only for machine-readable --json shapes; normal human formatted commands stay on the real gh. Supported --json fields are intentionally conservative. Common gh field names are mapped where the REST API uses different names, such as url, author, headRefName, headRefOid, baseRefName, baseRefOid, isDraft, databaseId, workflowName, and nameWithOwner. Run views also support the nested jobs field; Octopool composes its job/step metadata from the cache, exact API responses, or bounded public GitHub pages. gh search issues|prs is translated to a repo-scoped, cacheable GitHub Search request for the common plain-term -R owner/repo --state ... --json ... shape. Cache hits cost zero GitHub Search quota; misses use the pool's search bucket. Qualified search syntax such as author: or custom sort/match flags falls through to the real gh. PR search supports the issue-like fields returned by GitHub Search; PR-list-only fields such as headRefName fall through. gh pr checks uses the shared cache by default; ask for raw gh api conditional requests only when freshness matters more than quota. --jq runs after --json filtering, matching the usual agent workflow for small machine-readable reads.
The command falls through to the real gh without contacting Octopool when any of these hold:
- method is not
GET, or mutating field flags are present (-f,-F,--field,--raw-field,--paginate,--slurp). - a query key looks secret-bearing, or a header is outside the safe set (
accept,x-github-api-version,if-none-match,if-modified-since). --jqwas requested butjqis not installed.- a top-level subcommand or flag is not one of the supported read-only shapes.
Safe read-shaped requests are sent to Octopool first. Octopool owns the route and pool policy decision; on a cache miss it first uses token-free GitHub API/web/raw/Git endpoints for supported public shapes, then the configured app/PAT identity pool, writes eligible public responses to the shared cache, and returns the GitHub-shaped body. If the server says the read should run locally — unsupported route, public pooling disabled by policy, private/unverified repository, no usable identity, or identity pool depleted — the CLI runs the original command with the real gh and your local GitHub token.
Pagination is fail-closed: if bounded relay pagination cannot prove a complete PR detail, check set, or filtered issue list, the CLI delegates to real gh instead of returning a partial result. Non-integer --limit/-L values are rejected explicitly.
Any other gh subcommand (gh pr create, gh auth, unusual formatting flags, …) is passed straight through to the real GitHub CLI, with its exit code preserved.
#octopool health [--pool <id>]
Fetches GET /v1/pools/<pool>/health using the stored token. Returns identity counts and policy version.
#octopool stats [--pool <id>] [--since 24h] [--json]
Fetches GET /v1/pools/<pool>/stats using the stored token. The default human output shows the pool request count, service errors, expected local fallbacks, raw and successful-eligible cache hit rates, coalesced duplicate misses, caller-specific usage, D1 cache entries, and top route kinds. --since accepts 30m, 24h, or 7d style windows, capped at 30 days.
octopool stats
# pool: maintainers
# requests: 54 (1 service errors, 2 local fallbacks)
# cache: 82.4% hit (40 hits, 2 stale, 9 misses, 3 bypass, 0 unknown)
# eligible: 49/54 requests, 85.7% hit
# coalesced: 4 duplicate misses
# github: 42 saved, 12 backend
# top routes:
# pr_view: 31 req, 86.1% eligible hit, 1 stale, 5 miss, 0 bypass, 0 errors, 1 fallback
Use --json for dashboards or scripts that want the raw aggregate:
octopool stats --since 7d --json
#octopool request --path <p> [--method GET] [--query k=v] [--header k=v] [--route-hint k=v]
Debug/admin raw wrapper over POST /v1/github/request. Prints the full relay envelope. --route-hint pr_head_sha=<sha> or --route-hint pr_state=closed can be used for state-aware PR subresource cache probes.
#octopool admin caller|identity ...
Admin provisioning. Requires an admin token. See Admin & provisioning.
#Token and URL safety
- A saved caller token is only sent to the saved Octopool URL. Overriding
--url(orOCTOPOOL_URL) to a different host requires an explicitOCTOPOOL_TOKEN, or a freshoctopool loginfor that URL. This prevents leaking the token to an attacker-supplied endpoint. - Once a request reaches Octopool, relay policy denials fail closed; they are not silently retried against the real
ghunless Octopool returns the explicitfallback_localsignal for a safe read.
#Environment variables
These are dev/CI escape hatches, not the everyday UX:
OCTOPOOL_URL— base URL override.OCTOPOOL_TOKEN— caller token override (required to use a non-saved URL).OCTOPOOL_POOL— pool id (defaultmaintainers).OCTOPOOL_GH_PATH— path to the realghbinary.OCTOPOOL_NO_FALLBACK=1— fail instead of running realghafter Octopool returnsfallback_local, useful for proving relay/cache coverage.OCTOPOOL_ADMIN_TOKEN— admin token foroctopool admin.OCTOPOOL_ALLOW_INSECURE_LOGIN=1— permit non-HTTPS login for local dev.
#Server discovery
Self-hosted Octopool servers expose:
GET /.well-known/octopool
Response shape:
{
"service": "octopool",
"version": 1,
"api_base": "https://octopool.your-org.dev",
"app_base": "https://octopool.your-org.dev",
"default_pool": "maintainers",
"allowed_org": "your-org",
"auth": {
"cli_github_token": true,
"web_login": true
},
"min_cli_version": "0.2.2"
}
octopool.dev advertises itself as the API base and https://octopool.openclaw.ai as the browser app base. A one-domain self-host can use the same origin for both.