KNOLO / HUBPublish
CLI / REFERENCE

Pin knowledge the way you pin software.

The Hub CLI surface lives in @knolo/cli (knolo-core). Hub ships HTTP. Downloads go to Vercel Blob, never through Hub.

01knolo add

GET the version manifest from https://hub.knolo.dev (Cache-Control: no-store), refuse 410 unless --force, refuse an empty url, GET the Blob URL, SHA-256 the body, compare to manifest.sha256, then mount locally. Do not send Hub tokens to Blob. Do not increment anything on Hub — pulls increment on the manifest GET.

knolo search refunds
knolo info acme/refund-policy
knolo add acme/refund-policy@1.2.0
# or: knolo search refunds --registry https://hub.knolo.dev

02Lockfile

Keep the version and digest together so an application can reproduce the same artifact.

{
  "name": "acme/refund-policy",
  "version": "1.2.0",
  "sha256": "21a9d04e…7a12",
  "stateRoot": "0x4d19…f0bc",
  "license": "Apache-2.0"
}

03Login stores a Bearer token

Create a kno_… token at /dashboard/tokens (GitHub session). knolo login stores it locally. Every write call must send Authorization: Bearer kno_… — the Bearer scheme is required. Omitting it yields 401 Sign in required even when the secret is valid. knolo whoami does not call Hub.

knolo login --token kno_…
curl -sS -H "Authorization: Bearer kno_…" https://hub.knolo.dev/api/v1/account

04knolo publish is not wired yet

@knolo/cli 5.2.0 still stubs knolo publish / knolo yank with “Hub write APIs do not accept CLI tokens yet”. Hub does accept Bearer tokens. Treat that CLI error as a missing command, not as Hub policy. Until the CLI ships publish, use /publish in the browser or the HTTP sequence below. Do not call POST /api/v1/tokens with the CLI key (session only).

05Publish over HTTP

Hash the .knolo, POST /api/upload/token with the Bearer header, PUT bytes to the returned public upload.url (abort if the host is .private.), then complete / verify / draft / release. complete rejects private Blob URLs. Do not send the kno_ token to Blob.

POST /api/upload/token          { sha256, contentLength }
PUT  <upload.url>               .knolo bytes
POST /api/upload/complete       { sha256, url, sizeBytes, pathname }
POST /api/v1/publish/verify     { sha256 }
GET  /api/v1/publish/jobs/:id   until passed
POST /api/v1/publish/drafts     { sha256, slug, version, license, attested: true, … }
POST /api/v1/publish/drafts/:id/release