Loading...
Loading...
Review GitBook change requests from Claude Code by calling the GitBook REST API directly with curl (no CLI) — the reviewer-side companion to cr-create (the authoring side over the same API). Discover the change requests that need review (filter by who opened them, by space, or across a whole org), get the GitBook app link to review the diff, summarize what actually changed in a CR, then leave comments and optionally submit a review verdict (approve / request changes). Use this whenever someone wants to review docs change requests over the raw API (curl/HTTP), asks "what CRs are open / waiting on me / opened by <person>", "show me the change requests in <space>/<org>", "summarize what changed in this CR", "review this change request", "leave a comment on a CR", or "approve / request changes on a CR". For the authoring side (create a CR, push content, request reviewers, fix comments) over the API, use cr-create instead.
npx skill4agent add gitbookio/gitbook-skills cr-reviewhttps://api.gitbook.com/v1curlcr-creategbapihttps://api.gitbook.com/v1GITBOOK_TOKEN.envcurl --fail-with-bodyset -a; [ -f .env ] && . ./.env; set +a # load GITBOOK_TOKEN
gbapi() { # gbapi METHOD /path [extra curl args…]
local method="$1" apipath="$2"; shift 2 # NB: not `path` — in zsh that is tied to $PATH
curl -sS --fail-with-body -X "$method" \
"https://api.gitbook.com/v1${apipath}" \
-H "Authorization: Bearer ${GITBOOK_TOKEN}" \
-H "Content-Type: application/json" "$@"
}jqgbapi<org><space><cr><pageId>https://api.gitbook.com/v1| Step | Method + path | Notes |
|---|---|---|
| Who am I | | your own user ID is |
| Resolve a person → user ID | | match on |
| List orgs (to get IDs) | | |
| List spaces in an org | | |
| Discover CRs across an org | | |
| Discover CRs in a single space | | |
| CR detail | | |
| Link to review the diff | use | |
| Link to the rendered preview | | |
| Structural change summary | | entries like |
| Per-page prose diff | CR side | input to a prose summary only — never paste this as a line-by-line diff; point the user at |
| Existing comments (context) | | bodies at |
| Leave a comment (GATE) | | posts publicly, notifies the author |
| Submit a verdict (GATE) | | records a real review |
| Existing reviews / your own | |
statusapprovedchanges-requestedChangeRequestReviewStatusPOST …/mergeauthorsstatuscreatorspacesiterequestedReviewercontributororderBystatusdraftopenarchivedmergedstatusstatus=openopenauthors…/comments?authors=<id>postedBy.idGET /user.idjqauthorslimitnext.pagepage=page=1curljqPATHapi.gitbook.comGITBOOK_TOKEN.envgbapi GET /userGET /orgsGET /orgs/<org>/spacescreatorrequestedReviewerGET /orgs/<org>/members?search=…gbapiurls.appurls.appurls.appSiteurls.previewGET /orgsGET …/spaceslimitnext.pagepage=titlesubjectPOST …/commentsPOST …/reviewscreatorrequestedReviewermembers?search=status=openstatusgbapi GET /user | jq '{id, displayName, email}' # confirm auth + your OWN user ID
gbapi GET "/orgs?limit=100" | jq -r '.items[] | "\(.id)\t\(.title)"' # org IDs
gbapi GET "/orgs/<org>/spaces?limit=100" | jq -r '.items[] | "\(.id)\t\(.title)"' # space IDs in an orglimitnext.pagepage=<org><space><cr><pageId># Resolve a person to a user ID (for creator / requestedReviewer)
gbapi GET "/orgs/<org>/members?search=ada@example.com" \
| jq -r '.items[] | "\(.id)\t\(.user.displayName)\t\(.user.email)"'
# → match on user.displayName / user.email; the user ID is `id`
# Discover CRs across an org — open ones, optionally narrowed by creator/space
gbapi GET "/orgs/<org>/change-requests?status=open" | jq '.items'
gbapi GET "/orgs/<org>/change-requests?status=open&creator=<userId>" | jq '.items'
gbapi GET "/orgs/<org>/change-requests?status=open&space=<space>" | jq '.items'
ME=$(gbapi GET /user | jq -r .id)
gbapi GET "/orgs/<org>/change-requests?requestedReviewer=$ME" | jq '.items' # "assigned to me"
# Discover CRs in a single space
gbapi GET "/spaces/<space>/change-requests?status=open" | jq '.items'
# Inspect one CR (subject, status, author, comment count, app link)
gbapi GET "/spaces/<space>/change-requests/<cr>" \
| jq '{number, subject, status, author: .createdBy, comments, url: .urls.app}'
# Summarize what changed — structural first
gbapi GET "/spaces/<space>/change-requests/<cr>/changes" | jq '.'
# → page_created / page_edited entries with page.title and page.path
# Optional deeper per-page prose diff: CR content vs base content
gbapi GET "/spaces/<space>/change-requests/<cr>/content/page/<pageId>?format=markdown" # CR side
gbapi GET "/spaces/<space>/content/page/<pageId>?format=markdown" # base side
# diff the two markdown blobs client-side
# Read existing comments for context (classify on postedBy.id)
gbapi GET "/spaces/<space>/change-requests/<cr>/comments?format=markdown&status=all" | jq '.items'
# Leave a comment (GATE)
gbapi POST "/spaces/<space>/change-requests/<cr>/comments" \
--data '{"body":{"markdown":"Looks good — one nit on the retry section."}}' | jq '.'
# add "page":"<pageId>" (or "node":"<nodeId>") in the body to anchor the comment
# Submit a verdict (GATE)
gbapi POST "/spaces/<space>/change-requests/<cr>/reviews" --data '{"status":"approved"}' | jq '.'
gbapi POST "/spaces/<space>/change-requests/<cr>/reviews" --data '{"status":"changes-requested"}' | jq '.'
# optionally include "comment":{"markdown":"…"} in the same bodyrequestedReviewer=$MEGET /userGET /orgs/<org>/members?search=status=opencreatedBy.displayNamecommentsupdatedAturls.app…/changespage_createdpage_editedpage.titlepage.path…/change-requests/<cr>/content/page/<pageId>?format=markdown…/spaces/<space>/content/page/<pageId>?format=markdownurls.app{% @mermaid/diagram %}urls.appurls.previewSitecr-createpostedBy.id == "gitbook:agent"pagenode"page":"<pageId>""node":"<nodeId>"POST …/commentsidapprovedchanges-requested"comment":{"markdown":"…"}POST …/reviews{"status":"<verdict>"}requested-reviewersreviewsGET …/reviewscurljqgbapicr-create.envGITBOOK_TOKEN