Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
26 changes: 17 additions & 9 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <path>.tar.gz --version 0.3.9 --port 8787
node test/fixtures/make-fixture-cdn.mjs --tarball <path>.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 .
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -162,9 +170,9 @@ of printing JSON. Any script invoking the binary must redirect `</dev/null`
metadata sync) vs live-CDN jobs (`Install + smoke` matrix, npx-against-CDN)
which run only on push to main or manual dispatch — never on PRs, because a
CDN gap would fail every PR.
- The live CDN serves 0.3.9 (latest aliases + v-prefixed pinned tarballs
for 0.3.0 through 0.3.9, with `manifest.json` + `.sha256`
sidecars; `channels.stable` = 0.3.9); all smoke legs are required.
- The live CDN serves 0.3.10 (latest aliases + v-prefixed pinned tarballs
for 0.3.0 through 0.3.10, with `manifest.json` + `.sha256`
sidecars; `channels.stable` = 0.3.10); all smoke legs are required.
- `publish-npm.yml` (tag `v*`): asserts tag == package.json version → gates
on `generate-manifest.mjs --check` against the live CDN → publishes via
npm trusted publishing (OIDC, `id-token: write`, npm ≥ 11.5.1 — no token
Expand Down
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ The npm package is a small launcher: on first run it downloads the matching
platform distribution from Cloudglue's CDN (cached under
`~/.tinycloud/versions/<version>/`), 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
```
Expand All @@ -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 <key> # or: export CLOUDGLUE_API_KEY=...
tinycloud setup --check --json # verify
```
Expand Down Expand Up @@ -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:

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
32 changes: 20 additions & 12 deletions skills/tinycloud-init/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,26 @@ at https://tinycloud.sh. Windows is unsupported — use WSL2.
tinycloud setup --check --json </dev/null
```

If `data.ok` is `true`, go to step 3. Otherwise tell the user: cloud
features run through a Cloudglue account — keys live at
[app.cloudglue.dev](https://app.cloudglue.dev) (usage billed per the
[rate card](https://app.cloudglue.dev/home/billing/rate-card)). Ask them to
paste their API key, then configure it via stdin so the key never lands in
shell history or process args:

```bash
printf '%s' "<key>" | 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' "<key>" | tinycloud setup cloudglue --stdin
```

Then re-run `tinycloud setup --check --json` and confirm `data.ok == true`.

## 3. Prove it works (free)

Expand Down
7 changes: 4 additions & 3 deletions skills/tinycloud/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ npm install -g @cloudglue/tinycloud
```

Credentials (required for cloud verbs): `tinycloud setup cloudglue --api-key <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

Expand All @@ -51,7 +52,7 @@ credentials), `error` (`{code, message, retryable}`).
|---|---|
| `ready` | consume `data` / `ref` / file paths and continue |
| `pending` | async job started — `tinycloud jobs wait <meta.job_id> --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 <url> --json` |
| `paused` | stop; surface `resume` info to the user (resume is not automated in 0.3.x) |
Expand Down
4 changes: 2 additions & 2 deletions skills/tinycloud/reference/envelope.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
Expand Down Expand Up @@ -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 <id> --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` |
Expand Down
6 changes: 6 additions & 0 deletions skills/tinycloud/reference/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 11 additions & 0 deletions skills/tinycloud/reference/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <key> # persist the key
# or
export CLOUDGLUE_API_KEY=<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).

Expand Down
21 changes: 21 additions & 0 deletions skills/tinycloud/reference/verbs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -427,6 +428,26 @@ tinycloud setup --list --json # known services
tinycloud setup cloudglue --api-key <key> # or --stdin
```

### login — browser sign-in (network, 0.3.10+)

```bash
tinycloud login [--no-browser] [--web-url <url>] [--label <text>] --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 <key>` or `$CLOUDGLUE_API_KEY`.

## Shared flags

Output: `--json` (force JSONL envelopes), `--pretty` (one JSON array),
Expand Down
2 changes: 1 addition & 1 deletion skills/tinycloud/tinycloud-skill.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
Loading