From 8d261120bfd93094ebfb3e0ca5895e2d5715d568 Mon Sep 17 00:00:00 2001 From: KDR Date: Sat, 11 Jul 2026 09:38:43 -0700 Subject: [PATCH] Prepare for tinycloud 0.3.10: browser sign-in (`tinycloud login`) device-auth flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Version parity + additive docs for the 0.3.10 binary, which adds a new `login` verb (feature `login.v1`) — an OAuth-style device-authorization browser sign-in that provisions and saves a normal Cloudglue API key exactly like a pasted key (raw key never printed). It's a real command present in `commands --json` (16 verbs now; cost class network, no auth), excluded only from the LLM agent's tool set because it blocks on an interactive flow. - Versions → 0.3.10: package.json, plugin.json, marketplace.json (×2), tinycloud-skill.json skill_version. - Floor KEPT at 0.3.7 (min_version + required_features unchanged): `login` is an onboarding/credentials convenience, not a video op — requiring it would hard-fail the whole skill on 0.3.7-0.3.9 for no video reason. Paste-key + $CLOUDGLUE_API_KEY remain the documented fallback. Preflight/skill.json stay in sync (23 features, >=0.3.7 <0.4.0). - Docs (additive, version-annotated): verbs.md (login row + section), setup.md and SKILL.md credentials paths, tinycloud-init step 2 (browser sign-in as the recommended connect method, user-run; stdin paste as the agent-drivable fallback), envelope.md + SKILL.md needs_credentials row (setup.login_command), glossary.md term, README Commands table + Setup, CLAUDE.md verb count/CDN. Verified against the real 0.3.10 dist tarball (version 0.3.10+1364424, feature login.v1 present, `login` in commands --json, command_spec_revision 3105fe90fed9): npm test 42/42, shellcheck, plugin validate, preflight/skill sync, and smoke-test.sh (EXPECTED_VERSION=0.3.10) all green. --- .claude-plugin/marketplace.json | 4 ++-- .claude-plugin/plugin.json | 2 +- CLAUDE.md | 26 +++++++++++++-------- README.md | 10 +++++--- package.json | 2 +- skills/tinycloud-init/SKILL.md | 32 ++++++++++++++++---------- skills/tinycloud/SKILL.md | 7 +++--- skills/tinycloud/reference/envelope.md | 4 ++-- skills/tinycloud/reference/glossary.md | 6 +++++ skills/tinycloud/reference/setup.md | 11 +++++++++ skills/tinycloud/reference/verbs.md | 21 +++++++++++++++++ skills/tinycloud/tinycloud-skill.json | 2 +- 12 files changed, 93 insertions(+), 34 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 7f1165a..1b9486e 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -7,14 +7,14 @@ }, "metadata": { "description": "Deep video and image work for coding agents: analyze, describe, search, caption, clip, detect faces, and publish via the tinycloud CLI.", - "version": "0.3.9" + "version": "0.3.10" }, "plugins": [ { "name": "tinycloud", "source": "./", "description": "Video and image understanding and editing via the tinycloud CLI (Cloudglue): watch/see/extract/search/ask/face over videos and images, captions, clips, collections, plus one-command workflows for sales coaching, blog posts, ad analysis, meeting breakdowns, and YouTube publishing.", - "version": "0.3.9", + "version": "0.3.10", "author": { "name": "Cloudglue" }, "homepage": "https://tinycloud.sh", "repository": "https://github.com/cloudglue/tinycloud", diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index ee5e592..2e0ce4e 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "tinycloud", "displayName": "Tinycloud Video", "description": "Video and image understanding and editing via the tinycloud CLI (Cloudglue): watch/see/extract/search/ask/face over videos and images, captions, clips, collections, and one-command video workflows.", - "version": "0.3.9", + "version": "0.3.10", "author": { "name": "Cloudglue", "url": "https://cloudglue.dev" }, "homepage": "https://tinycloud.sh", "repository": "https://github.com/cloudglue/tinycloud", diff --git a/CLAUDE.md b/CLAUDE.md index 1809287..a7b4d52 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,16 +28,16 @@ node --test test/unit.test.mjs # just the unit suite TINYCLOUD_TEST_TARBALL=~/Downloads/tinycloud-darwin-arm64.tar.gz npm test # e2e against a real dist tarball # Contract smoke tests against an installed/extracted binary -TINYCLOUD_CMD=/path/to/tinycloud EXPECTED_VERSION=0.3.9 bash scripts/smoke-test.sh +TINYCLOUD_CMD=/path/to/tinycloud EXPECTED_VERSION=0.3.10 bash scripts/smoke-test.sh # Serve a tarball as a fake CDN (modes: --corrupt, --no-manifest) -node test/fixtures/make-fixture-cdn.mjs --tarball .tar.gz --version 0.3.9 --port 8787 +node test/fixtures/make-fixture-cdn.mjs --tarball .tar.gz --version 0.3.10 --port 8787 TINYCLOUD_DIST_URL=http://127.0.0.1:8787 TINYCLOUD_INSTALL_DIR=$(mktemp -d) node bin/tinycloud.js --version --json TINYCLOUD_DIST_URL=http://127.0.0.1:8787 bash install.sh --install-dir $(mktemp -d)/bin # Release manifest tooling (maintainer) -node scripts/generate-manifest.mjs --version 0.3.9 --from-cdn # build manifest + .sha256 sidecars -node scripts/generate-manifest.mjs --check --version 0.3.9 # verify live CDN matches manifest +node scripts/generate-manifest.mjs --version 0.3.10 --from-cdn # build manifest + .sha256 sidecars +node scripts/generate-manifest.mjs --check --version 0.3.10 # verify live CDN matches manifest # Plugin metadata validation claude plugin validate . @@ -103,13 +103,21 @@ stdout (logs on stderr) with `status`: → exit codes 0/0/2/3/3/0/1. `tinycloud commands --json` is the authoritative flag list — verify doc claims against it, not memory (a doc bug shipped once because `--cached` only exists on watch/see/extract/caption/face/workflow). As -of 0.3.9 (command surface unchanged since 0.3.8) there are 15 verbs: `see` +of 0.3.10 there are 16 verbs: `see` (0.3.7+) analyzes an **image** (file-level, JPEG/PNG/WebP — the image counterpart of `watch`) and `extract` also takes an image source (features `see.v1`, `extract.images.v1`); 0.3.8 adds `publish video --clip-only` (hard clip: `data.moment_url` gains `&clip=hard` so the share page plays only the moment; feature -`publish.video.moment.hard.v1`). The +`publish.video.moment.hard.v1`); 0.3.10 adds the `login` verb (feature +`login.v1`) — a browser device-authorization sign-in +(`tinycloud login` → best-effort opens the Cloudglue dashboard, mints a normal +`cg-` API key, saves it to config exactly like a pasted key; the raw key never +touches stdout/envelopes/logs). Unlike the host-level `profile` verb, `login` +IS a normal command **present in `commands --json`** (cost class `network`, +`requires_auth: false`) — it is excluded only from the LLM agent's tool set +(it blocks on a ~10-min interactive flow). Paste-key + `$CLOUDGLUE_API_KEY` +remain fully supported. The host-level `profile` verb and the leading global flags `--home`/`--profile` (also `$TINYCLOUD_HOME`; 0.3.3+) relocate state and are intentionally absent from `commands --json` — like the launcher's install/update, they're CLI/host @@ -162,9 +170,9 @@ of printing JSON. Any script invoking the binary must redirect `/`), verifies its checksum, and execs the real binary. The package version pins the binary version, so -`npx @cloudglue/tinycloud@0.3.9` always runs tinycloud 0.3.9. It also adds two +`npx @cloudglue/tinycloud@0.3.10` always runs tinycloud 0.3.10. It also adds two wrapper commands: ```bash -tinycloud install --version 0.3.9 # pre-download a version +tinycloud install --version 0.3.10 # pre-download a version tinycloud install --latest # install latest stable and pin to it tinycloud update # move to latest stable, prune old versions ``` @@ -38,9 +38,12 @@ supported — use WSL2. ### Setup -Cloud features need a Cloudglue API key: +Cloud features need a Cloudglue API key. The quickest way is browser sign-in +(0.3.10+) — it provisions a key for you, no copy-paste: ```bash +tinycloud login # browser sign-in → provisions & saves a key (0.3.10+) +# or paste a key yourself: tinycloud setup cloudglue --api-key # or: export CLOUDGLUE_API_KEY=... tinycloud setup --check --json # verify ``` @@ -131,6 +134,7 @@ go to stderr) — pass `--json`. | `workflow` | Run packaged pipeline recipes (see below) | | `publish` | Publish HTML artifacts as Cloudglue Sites; share videos | | `setup` | Configure the Cloudglue API key and service connections | +| `login` | Browser sign-in — provisions & saves a Cloudglue API key (0.3.10+) | A few common invocations: diff --git a/package.json b/package.json index 20b9078..ea38884 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cloudglue/tinycloud", - "version": "0.3.9", + "version": "0.3.10", "description": "Agent CLI for deep video and image work, by Cloudglue. Downloads the tinycloud binary on first run.", "bin": { "tinycloud": "bin/tinycloud.js" diff --git a/skills/tinycloud-init/SKILL.md b/skills/tinycloud-init/SKILL.md index d408b12..21f9584 100644 --- a/skills/tinycloud-init/SKILL.md +++ b/skills/tinycloud-init/SKILL.md @@ -43,18 +43,26 @@ at https://tinycloud.sh. Windows is unsupported — use WSL2. tinycloud setup --check --json " | tinycloud setup cloudglue --stdin -``` - -Re-run `tinycloud setup --check --json` and confirm `data.ok == true`. +If `data.ok` is `true`, go to step 3. Otherwise cloud features run through a +Cloudglue account (usage billed per the +[rate card](https://app.cloudglue.dev/home/billing/rate-card)) — connect one of +two ways: + +- **Browser sign-in (recommended; tinycloud 0.3.10+).** Ask the user to run + `tinycloud login` **themselves in their terminal** — it's an interactive + browser flow you can't drive from here. It opens the Cloudglue dashboard, they + approve a short code, and a key is provisioned and saved automatically (no + copy-pasting keys). +- **Paste an API key.** If they'd rather paste an existing key (or their + tinycloud predates `login`), have them get one at + [app.cloudglue.dev](https://app.cloudglue.dev) and configure it via stdin so + the key never lands in shell history or process args — this path you can run: + + ```bash + printf '%s' "" | tinycloud setup cloudglue --stdin + ``` + +Then re-run `tinycloud setup --check --json` and confirm `data.ok == true`. ## 3. Prove it works (free) diff --git a/skills/tinycloud/SKILL.md b/skills/tinycloud/SKILL.md index cd07a4a..481eb60 100644 --- a/skills/tinycloud/SKILL.md +++ b/skills/tinycloud/SKILL.md @@ -37,8 +37,9 @@ npm install -g @cloudglue/tinycloud ``` Credentials (required for cloud verbs): `tinycloud setup cloudglue --api-key ` -(or `export CLOUDGLUE_API_KEY=...`). Verify with -`tinycloud setup --check --json` → `data.ok == true`. +(or `export CLOUDGLUE_API_KEY=...`), or, for a human at a terminal, +`tinycloud login` (0.3.10+) for browser sign-in that provisions and saves a key. +Verify with `tinycloud setup --check --json` → `data.ok == true`. ## 1. The envelope contract @@ -51,7 +52,7 @@ credentials), `error` (`{code, message, retryable}`). |---|---| | `ready` | consume `data` / `ref` / file paths and continue | | `pending` | async job started — `tinycloud jobs wait --timeout 120s --json` | -| `needs_credentials` | run the command in `setup.command` or set the env in `setup.env` | +| `needs_credentials` | run the command in `setup.command` (or `setup.login_command`, `tinycloud login`, for browser sign-in — 0.3.10+) or set the env in `setup.env` | | `needs_upload` | cloud upload required (runs through the user's Cloudglue account) — rerun without `--no-upload` or confirm with the user | | `needs_download` | fetch locally first: `tinycloud grab --json` | | `paused` | stop; surface `resume` info to the user (resume is not automated in 0.3.x) | diff --git a/skills/tinycloud/reference/envelope.md b/skills/tinycloud/reference/envelope.md index de6ebcd..a10a6d9 100644 --- a/skills/tinycloud/reference/envelope.md +++ b/skills/tinycloud/reference/envelope.md @@ -16,7 +16,7 @@ Envelope schema version: `"1"` (reported in `--version --json` as "meta": { "elapsed_ms": 1234, "requires": "cloud", "cache": { "identity": "hit" } }, "summary": "one-line human summary", "next": [ { "…": "suggested follow-up commands" } ], - "setup": { "service": "cloudglue", "env": ["CLOUDGLUE_API_KEY"], "command": "tinycloud setup cloudglue" }, + "setup": { "service": "cloudglue", "env": ["CLOUDGLUE_API_KEY"], "command": "tinycloud setup cloudglue", "login_command": "tinycloud login" }, "resume": { "run_id": "…", "paused_step": "…", "resume_command": "…" }, "error": { "code": "validation", "message": "…", "retryable": false } } @@ -44,7 +44,7 @@ Envelope schema version: `"1"` (reported in `--version --json` as | `ready` | 0 | `data` usable | consume and continue | | `pending` | 0 | `meta.job_id` set | `tinycloud jobs wait --timeout 120s --json`; do NOT start downstream work | | `paused` | 0 | `resume` present | stop; surface resume info (resume not automated in 0.3.x) | -| `needs_credentials` | 2 | `setup` present | run `setup.command` or set `setup.env` | +| `needs_credentials` | 2 | `setup` present | run `setup.command` (or `setup.login_command`, `tinycloud login`, browser sign-in — 0.3.10+) or set `setup.env` | | `needs_upload` | 3 | — | cloud upload required (runs through the user's Cloudglue account); rerun without `--no-upload` after confirming | | `needs_download` | 3 | — | materialize locally first (`tinycloud grab …`) | | `error` | 1 | `error` present | stop; report `error.message`; retry only if `error.retryable` | diff --git a/skills/tinycloud/reference/glossary.md b/skills/tinycloud/reference/glossary.md index 9b98392..1c6f9a1 100644 --- a/skills/tinycloud/reference/glossary.md +++ b/skills/tinycloud/reference/glossary.md @@ -14,6 +14,12 @@ connector?" or an envelope field needs explaining. - **tinycloud** — the agent CLI distributed from this repo (https://tinycloud.sh). Local verbs (`clip`, `search`, `setup`) run on your machine; cloud verbs call Cloudglue with your API key. +- **Browser sign-in / device login (0.3.10+)** — `tinycloud login` runs an + OAuth-style device-authorization flow: it prints a short code + verification + URL, opens the Cloudglue dashboard, and on approval mints a normal `cg-` API + key saved to config exactly like a pasted key (the raw key is never printed). + The interactive counterpart of `setup cloudglue --api-key`; paste-key and + `$CLOUDGLUE_API_KEY` remain fully supported for headless/scripted setup. ## Media and identity diff --git a/skills/tinycloud/reference/setup.md b/skills/tinycloud/reference/setup.md index d9c13ab..fe2cbf6 100644 --- a/skills/tinycloud/reference/setup.md +++ b/skills/tinycloud/reference/setup.md @@ -31,11 +31,22 @@ Usage is billed to that key per the [rate card](https://app.cloudglue.dev/home/billing/rate-card). ```bash +tinycloud login # browser sign-in → provisions & saves a key (0.3.10+) +# or paste/point at a key yourself: tinycloud setup cloudglue --api-key # persist the key # or export CLOUDGLUE_API_KEY= # env only, nothing persisted ``` +`tinycloud login` (0.3.10+) runs an OAuth-style device sign-in: it best-effort +opens the Cloudglue dashboard, you approve a short code, and a normal `cg-` API +key is minted and saved to config exactly like a pasted key — you never handle +the key. It blocks on a browser flow (~minutes), so for headless or scripted +setup prefer `setup cloudglue --api-key` / `$CLOUDGLUE_API_KEY`. When a cloud +verb hits missing credentials, the `needs_credentials` envelope's `setup` object +now carries both `setup.command` (`tinycloud setup cloudglue`) and +`setup.login_command` (`tinycloud login`). + `frameio` is an optional service and requires interactive OAuth (`tinycloud setup frameio` inside the tinycloud agent TUI). diff --git a/skills/tinycloud/reference/verbs.md b/skills/tinycloud/reference/verbs.md index da131dd..cc4bedf 100644 --- a/skills/tinycloud/reference/verbs.md +++ b/skills/tinycloud/reference/verbs.md @@ -21,6 +21,7 @@ every verb. Regenerate doubts from it instead of trusting prose. | `workflow` | varies | no | Validate/plan/run workflow recipes | | `publish` | cloud | yes | Publish HTML/code artifacts as Cloudglue Sites; share videos | | `setup` | local | no | Credentials and service connections | +| `login` | network | no | Browser sign-in → provisions & saves a Cloudglue API key (0.3.10+) | Cloud verbs run through the configured Cloudglue API key. `caption`/`library`/`workflow` vary by what they end up doing. @@ -427,6 +428,26 @@ tinycloud setup --list --json # known services tinycloud setup cloudglue --api-key # or --stdin ``` +### login — browser sign-in (network, 0.3.10+) + +```bash +tinycloud login [--no-browser] [--web-url ] [--label ] --json +``` + +An OAuth-style **device-authorization** sign-in — the interactive counterpart of +`tinycloud setup cloudglue --api-key`. It prints a short code + a verification +URL, best-effort opens the Cloudglue dashboard, and polls until you approve; +approval mints a normal `cg-` API key that is saved to `~/.tinycloud/config.json` +(0600) exactly like a pasted key. The **raw key is never printed** — the `ready` +envelope's `data` carries only `{account, api_base_url, key_masked, config_path, +replaced_existing}` (progress code + URL go to **stderr**). `--no-browser` prints +the URL only (SSH/containers); `--web-url` (or `$CLOUDGLUE_WEB_URL`) points at a +non-default dashboard; `--label` names the provisioned key (default: hostname). +Revoke by deleting the key in the dashboard. Because it blocks on a +~10-minute human flow, `login` is a manual/onboarding command — don't script it +into an agent's tool loop; for headless/automated setup keep using +`tinycloud setup cloudglue --api-key ` or `$CLOUDGLUE_API_KEY`. + ## Shared flags Output: `--json` (force JSONL envelopes), `--pretty` (one JSON array), diff --git a/skills/tinycloud/tinycloud-skill.json b/skills/tinycloud/tinycloud-skill.json index 4d091bc..8b3e21f 100644 --- a/skills/tinycloud/tinycloud-skill.json +++ b/skills/tinycloud/tinycloud-skill.json @@ -1,5 +1,5 @@ { - "skill_version": "0.3.9", + "skill_version": "0.3.10", "tinycloud": { "min_version": "0.3.7", "supported_range": ">=0.3.7 <0.4.0",