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.13"
"version": "0.3.14"
},
"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.13",
"version": "0.3.14",
"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.13",
"version": "0.3.14",
"author": { "name": "Cloudglue", "url": "https://cloudglue.dev" },
"homepage": "https://tinycloud.sh",
"repository": "https://github.com/cloudglue/tinycloud",
Expand Down
29 changes: 22 additions & 7 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.13 bash scripts/smoke-test.sh
TINYCLOUD_CMD=/path/to/tinycloud EXPECTED_VERSION=0.3.14 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.13 --port 8787
node test/fixtures/make-fixture-cdn.mjs --tarball <path>.tar.gz --version 0.3.14 --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.13 --from-cdn # build manifest + .sha256 sidecars
node scripts/generate-manifest.mjs --check --version 0.3.13 # verify live CDN matches manifest
node scripts/generate-manifest.mjs --version 0.3.14 --from-cdn # build manifest + .sha256 sidecars
node scripts/generate-manifest.mjs --check --version 0.3.14 # verify live CDN matches manifest

# Plugin metadata validation
claude plugin validate .
Expand Down Expand Up @@ -103,7 +103,7 @@ 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.13 there are 16 verbs: `see`
of 0.3.14 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
Expand Down Expand Up @@ -146,8 +146,23 @@ non-numeric ignored). The speed menu lives in the Cloudglue-served embed
script, not the binary — no new verbs, flags, or feature ids (verbs stay 16,
features stay 33), the skill floor stays 0.3.12, and already-published sites
pick it up without republishing; the binary's embed guidance (skill reference,
kitchen sink, system prompt, publish notes) moved from v6 to v7 wording. The
host-level `profile` verb and the leading global flags `--home`/`--profile`
kitchen sink, system prompt, publish notes) moved from v6 to v7 wording.
0.3.14 adds **opt-in Open Graph link previews** (SDK bumped to 0.7.20; feature
`publish.link.preview.v1`, features 33→34, verbs stay 16): `publish` and
`publish video` take `--link-preview none|full`, and site publish also takes
`--preview-title` / `--preview-image` (validated as an absolute http(s) url
before any upload). Public sites/shares always unfurl — a public site's card
comes from the `og:*` tags in the author's own HTML, which is why the embed
docs now tell generators to emit them on every public publish. Private sites
and shares are redirected to sign-in before an unfurl bot sees anything, so
`full` opts them into a metadata-only stub; that makes the card fields
publicly readable (content, video, tokens, and cookies never leak, and
playback stays sign-in gated), so every doc surface says to ask the user
first. Flipping the setting on an existing site is a settings PATCH with no
re-upload, reported as the new `settings-only` publish action. Because the
skill teaches the flags, the floor was raised to 0.3.14 (the 0.3.12
floor-raise pattern — the dist PR merges only after CDN `channels.stable` =
0.3.14). 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
concerns, not video operations.
Expand Down
4 changes: 2 additions & 2 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.13` always runs tinycloud 0.3.13. It also adds two
`npx @cloudglue/tinycloud@0.3.14` always runs tinycloud 0.3.14. It also adds two
wrapper commands:

```bash
tinycloud install --version 0.3.13 # pre-download a version
tinycloud install --version 0.3.14 # pre-download a version
tinycloud install --latest # install latest stable and pin to it
tinycloud update # move to latest stable, prune old versions
```
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.13",
"version": "0.3.14",
"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
13 changes: 13 additions & 0 deletions skills/tinycloud/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,19 @@ Authoring your own recipes: [reference/workflow-authoring.md](reference/workflow
(`<cg-playlist>`, `<cg-grid>`, `<cg-chapters>`) rather than hand-rolled
players, galleries, or segment-list JS — details in
[reference/verbs.md](reference/verbs.md).
- Link previews (0.3.14+): how a pasted link unfurls in Slack/iMessage/Notion.
A **public** site's card comes from the HTML you generate — put `og:title`,
`og:description`, `og:image` (absolute URL — a share's `preview_url` works),
`og:url`, and `twitter:card` in the `<head>` of every public page, or the
link renders as a bare URL (bots don't run JS; never emit
`twitter:player`/`og:video`). A **private** site or share never reaches the
bot, so its card is off by default — opt in with `--link-preview full`
(private sites also take `--preview-title` / `--preview-image`; a private
share reuses its own title, description, and thumbnail). ⚠️ Ask the user
before turning it on: it makes those card fields readable by anyone with the
link (content and playback stay sign-in gated), and platforms cache per exact
URL, so turning it back off does not retract posted cards. Details in
[reference/verbs.md](reference/verbs.md).
- Live-API discovery components (0.3.6+): the same embed script also defines
collection-scoped, **private-site-only** elements that let viewers search/chat
inside a published site — `<cg-chat>`, `<cg-search>`, `<cg-deep-search>`,
Expand Down
10 changes: 10 additions & 0 deletions skills/tinycloud/reference/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ connector?" or an envelope field needs explaining.
events re-dispatched on the element) for custom site HTML, and plays
standalone or inside the container components (`<cg-playlist>`,
`<cg-grid>`, `<cg-chapters>`) — see reference/verbs.md.
- **Link preview** — the Open Graph card a platform (Slack, iMessage, Notion,
Discord) renders when someone pastes a site or share link. Public sites and
shares always preview: a public site's card comes from the `og:*` tags in
the HTML you generate, a public share's from its title/description/thumbnail.
Private sites and shares are redirected to sign-in before an unfurl bot sees
anything, so they render a bare "Sign in" card unless opted in with
`--link-preview full` (0.3.14+, feature `publish.link.preview.v1`; private
sites also take `--preview-title` / `--preview-image`). Opting in makes those
card fields publicly readable — content and playback stay sign-in gated — so
ask the user first. See reference/verbs.md.
- **Discovery components (live API, 0.3.6+)** — the same embed script also
defines four collection-scoped, **private-site-only** elements that let a
viewer search or chat inside a published site and play results inline via
Expand Down
53 changes: 51 additions & 2 deletions skills/tinycloud/reference/verbs.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,8 @@ tinycloud workflow <name> <source> [--param k=v] [--segment <s>] [--out <dir>]

```bash
tinycloud publish <html-file-or-dir> [--name <site-name>]
[--visibility public|private] --json
[--visibility public|private]
[--link-preview none|full] [--preview-title <text>] [--preview-image <url>] --json
tinycloud publish list --json # sites for this account, with URLs
tinycloud publish unpublish <site-ref> --json # site_id, site name, or the --name label
```
Expand All @@ -343,11 +344,49 @@ site itself gets a generated name (e.g. `young-fire-2486`) shown by
`publish list`. `unpublish` resolves any of: the `site_id` UUID, the
generated site name, or your `--name` label.

**Link previews (0.3.14+, `publish.link.preview.v1`)** — how a pasted link
unfurls in Slack, iMessage, Notion, Discord. The two visibilities work
completely differently:

- **Public site** — needs no flags. Its HTML reaches the unfurl bot verbatim,
so the card *is* whatever Open Graph tags the page carries. **Emit them in
the `<head>` of every public page you generate** — `og:title`,
`og:description`, `og:image` (an **absolute** URL — a share's `preview_url`
works), `og:url`, `twitter:card` — because a regenerated page without them
silently reverts the card to a bare link. Bots don't run JavaScript, so the
tags must be in the static HTML. Never emit `twitter:player` or `og:video`
(unfurlers ignore them for our domains and can degrade the card).
- **Private site** — the edge gate redirects bots to sign-in before any HTML
is served, so OG tags in the page are never seen and the link unfurls as a
bare "Sign in" card. Opt in instead with `--link-preview full`, plus
`--preview-title` (falls back to the generated site name) and
`--preview-image` (**must be publicly fetchable** — site assets sit behind
the same gate the bot can't pass, so use a share's `preview_url`; prefer a
long-lived unsigned URL, since unfurl caches hold the exact URL). The card
description is the site description. Pass `""` to either flag to clear it.

`--link-preview` is flippable on an **existing** site without republishing
content: the run reports `action: "settings-only"` (a settings PATCH, no
re-upload, no new version). The state comes back as `data.link_preview` (plus
`data.preview_title` / `data.preview_image_url`) and shows in `publish list`
rows as `link-preview=full`. `--preview-title`/`--preview-image` require
`--link-preview full`, and a non-absolute `--preview-image` errors before any
upload.

⚠️ **Ask the user before opting a private site in.** `--link-preview full`
makes the card title, the site description, and the card image readable by
anyone who fetches the link — the user-agent check only *routes*; the setting
is the security boundary. Nothing else leaks (no site content, video, tokens,
or cookies; the site stays sign-in gated). Platforms cache per exact URL and
rehost the image, so flipping back to `none` stops *future* unfurls but does
not retract already-posted cards.

### publish video — share a video

```bash
tinycloud publish video <source> [--visibility public|private] # default public
[--name <title>] [--segment-id <id>] [--clip-start <s> --clip-end <e> [--clip-only]] --json
[--name <title>] [--segment-id <id>] [--clip-start <s> --clip-end <e> [--clip-only]]
[--link-preview none|full] --json
tinycloud publish video list [--in <source>] [--visibility public|private] --json
tinycloud publish video unpublish <share-id | source> --json # --visibility disambiguates
```
Expand Down Expand Up @@ -385,6 +424,16 @@ feature id.
`&clip=hard` and fall back to the soft window. It shapes the viewing
experience, not access control — anyone with the bare `share_url` still has
the whole video; restrict access with `--visibility private`.
- Link previews (0.3.14+): a PUBLIC share page always unfurls in Slack with a
card built from its title, description, and thumbnail. A PRIVATE share is
redirected to sign-in before the bot sees anything, so it unfurls as a bare
"Sign in" card unless you pass `--link-preview full`, which serves bots a
metadata-only stub built from those same three fields. It comes back as
`data.share.link_preview`, and re-running flips it on an existing share
(a PATCH — no new share). Playback stays sign-in gated in every mode.
⚠️ Ask the user first: `full` makes the share's title, description, and
thumbnail readable by anyone who fetches the link, and platforms cache per
exact URL, so turning it back off does not retract already-posted cards.

When generating custom site HTML around a `<cg-video>` embed, use the
component's built-ins instead of reinventing them. It defaults to a
Expand Down
4 changes: 2 additions & 2 deletions skills/tinycloud/scripts/preflight.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ set -u

# Mirror tinycloud-skill.json: min_version / supported_range upper bound
# (CI diffs these against the manifest).
MIN_VERSION="0.3.12"
MIN_VERSION="0.3.14"
MAX_VERSION_EXCLUSIVE="0.4.0"
INSTALL_CMD='curl -fsSL https://app.cloudglue.dev/tinycloud.sh | bash'
# Kept in sync with ../tinycloud-skill.json required_features (CI diffs them).
REQUIRED_FEATURES="envelope.v1 watch.v1 watch.speech.v1 see.v1 extract.v1 extract.images.v1 caption.v1 search.v1 probe.v1 ask.v1 clip.v1 grab.v1 face.v1 jobs.v1 library.collections.v1 library.collections.create.v1 library.collections.mutate.v1 library.collections.entities.v1 library.sync.url.v1 workflow.v1 publish.v1 publish.manage.v1 publish.video.v1 setup.v1"
REQUIRED_FEATURES="envelope.v1 watch.v1 watch.speech.v1 see.v1 extract.v1 extract.images.v1 caption.v1 search.v1 probe.v1 ask.v1 clip.v1 grab.v1 face.v1 jobs.v1 library.collections.v1 library.collections.create.v1 library.collections.mutate.v1 library.collections.entities.v1 library.sync.url.v1 workflow.v1 publish.v1 publish.manage.v1 publish.video.v1 publish.link.preview.v1 setup.v1"

# 1) Binary present and responsive?
if ! command -v tinycloud >/dev/null 2>&1; then
Expand Down
7 changes: 4 additions & 3 deletions skills/tinycloud/tinycloud-skill.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"skill_version": "0.3.13",
"skill_version": "0.3.14",
"tinycloud": {
"min_version": "0.3.12",
"supported_range": ">=0.3.12 <0.4.0",
"min_version": "0.3.14",
"supported_range": ">=0.3.14 <0.4.0",
"required_features": [
"envelope.v1",
"watch.v1",
Expand All @@ -27,6 +27,7 @@
"publish.v1",
"publish.manage.v1",
"publish.video.v1",
"publish.link.preview.v1",
"setup.v1"
],
"envelope_schema": "1",
Expand Down
Loading