peertube · diff

git:20260711.a5f7e74 to git:20260829.83e07b9

203 added, 57 removed. Audit A to A.

---
name: peertube
- description: 'Browse PeerTube federated video from the terminal: view videos and channels,
- search across instances, check server stats, and manage your account. Uses OAuth2
- authentication with token persistence. Use when the user mentions PeerTube, federated
- video, decentralized video platforms, or browsing/uploading to a PeerTube instance.'
+ description: Browse PeerTube federated video from the terminal — instance stats, latest
+ videos, video detail, comment threads, channels, accounts, instance-local search, and
+ OAuth2 login with per-instance token persistence. Set PEERTUBE_SERVER to any instance;
+ point it at sepiasearch.org for fediverse-wide search. Use when the user mentions
+ PeerTube, federated video, SepiaSearch, or browsing a specific PeerTube instance.
+ Do not use this skill for YouTube/Vimeo uploads, video editing, or installing and
+ administering a PeerTube server.
license: MIT
- compatibility: Requires PEERTUBE_SERVER env var (set to your instance URL, e.g. https://watch.nousresearch.com),
- Python 3.8+, and the `requests` library. OAuth2 tokens persisted to ~/.config/peertube-cli/token.json.
+ compatibility: Requires Python 3.8+ and `requests`. Reads are anonymous; authenticated
+ commands (`me`, `my-videos`) need a token from `scripts/peertube login`. Tokens persist
+ per-instance to ~/.config/peertube/token.json (owner-only).
metadata:
- tags: peertube, federated-video, video-platform, activitypub, api-client
- sources: https://joinpeertube.org/, https://docs.joinpeertube.org/api/reference
+ tags: peertube, federated-video, activitypub, video-platform, sepiasearch, api-client
+ sources: https://docs.joinpeertube.org/api-rest-reference.html, https://sepiasearch.org/
---
- # peertube-cli — PeerTube Federated Video
+ # peertube — PeerTube federated video from the terminal
- Browse videos, channels, and server info on any PeerTube instance. Search across the fediverse, list channels, check your account stats, and manage authentication — all from the terminal.
+ Browse any PeerTube instance — a federated deployment, not a single API — from the
+ terminal: instance stats, latest videos, full video detail, comment threads, channels,
+ accounts, and instance-local search. Authenticate with OAuth2 only for your own account
+ commands. Every command is read-only except `login`/`logout`.
## Setup
- 1. Set the PeerTube instance URL:
+ 1. Choose the instance to talk to. Every command is per-instance; the API shape is
+ identical everywhere, but accounts, tokens, rules, and catalogs are not:
```bash
- export PEERTUBE_SERVER="https://your-instance.example.com"
+ export PEERTUBE_SERVER="https://<INSTANCE_HOST>" # e.g. https://tilvids.com
```
- 2. (Optional) Log in for authenticated operations:
+ To search the whole fediverse instead of one instance, point the same variable at the
+ public search index: `PEERTUBE_SERVER=https://sepiasearch.org` (same API shape — see
+ [references/search-and-discovery.md](references/search-and-discovery.md)).
+ 2. Nothing else is required to browse: videos, search, channels, comments, and instance
+ info are anonymous reads.
+
+ 3. (Optional) Log in only for your own account commands (`me`, `my-videos`):
+
```bash
- peertube-cli auth login --username "your-username" --password "your-password"
+ scripts/peertube login --username <NAME> --prompt
```
- The OAuth2 token is persisted to `~/.config/peertube-cli/token.json` and automatically reused. `--dry-run` works without authentication.
+ ### How authentication works
+ PeerTube uses plain OAuth2 with per-instance client credentials: the CLI anonymously
+ fetches the client pair from `GET /api/v1/oauth-clients/local` (singular `local`), then
+ exchanges your username/password for a bearer token at `POST /api/v1/users/token`
+ (`grant_type=password`, form-encoded). The token rides `Authorization: Bearer <token>`,
+ lives for the instance's configured lifetime (read `expires_in` from the response — do not
+ assume a fixed number), and is refreshed automatically when it expires. The token file is
+ written owner-only to `~/.config/peertube/token.json` keyed by server URL.
+ **Do not commit tokens** — they are account credentials; revoke with `scripts/peertube
+ logout` (`POST /users/revoke-token`) when done. Current production instances mask
+ `client_secret` in the API response; the CLI detects this and explains the workaround.
+ Details and wire-level error signatures:
+ [references/auth-and-tokens.md](references/auth-and-tokens.md).
+
## Essential Commands
- ### auth login — Authenticate to a PeerTube instance
+ ### server — instance stats and identity (anonymous)
```bash
- peertube-cli auth login --username "myuser" --password "mypassword" # login
+ scripts/peertube server # name, description, user/video/view counters
+ scripts/peertube server --json
```
- Token is saved to `~/.config/peertube-cli/token.json` and reused on subsequent calls. Tokens expire after the server-configured lifetime (typically 24h).
+ Composes `GET /config/about` + `GET /server/stats` (canonical paths — there is no
+ `/instance/stats`).
- ### server — Instance information
+ ### videos — browse the instance's uploads (anonymous)
```bash
- peertube-cli server # instance name, description, stats
- peertube-cli server --json # machine-readable
+ scripts/peertube videos # latest 15, offset pagination
+ scripts/peertube videos --limit 50 --offset 50
+ scripts/peertube videos --sort -views --json # popular first
```
- Shows: instance name, short description, total users, total videos, total views.
+ Pagination is `start`/`count` offsets (max count 100) — the API has **no `page`
+ parameter**.
- ### videos — Browse recent videos
+ ### search — find videos on THIS instance (anonymous)
```bash
- peertube-cli videos # last 12 videos
- peertube-cli videos --limit 24 # more results
- peertube-cli videos --json # machine-readable
+ scripts/peertube search --query "linux" # instance-local (searchTarget=local)
+ scripts/peertube search -q "docker" --limit 20 --json
+ PEERTUBE_SERVER="https://sepiasearch.org" scripts/peertube search -q "linux" # fediverse-wide
```
- Shows: title, duration, views, author/channel, publish date.
+ The bundled CLI performs **instance-local** search only (`searchTarget=local`). For
+ fediverse-wide search, point `PEERTUBE_SERVER` at SepiaSearch — same commands, wider
+ index. Search results carry `channel.host`/`url`, the origin instance of federated hits.
- ### search — Search videos across the fediverse
+ ### video — full detail for one video (anonymous)
```bash
- peertube-cli search --query "linux tutorial" # search videos
- peertube-cli search -q "peer" --limit 24 # more results
- peertube-cli search -q "docker" --json # machine-readable
+ scripts/peertube video --id <UUID> # numeric id, UUID, or shortUUID all work
+ scripts/peertube video --id <UUID> --json | jq '{name, description, views, url}'
```
- ### channels — List video channels
+ ### comments — top-level comment threads (anonymous)
```bash
- peertube-cli channels # all channels on the instance
- peertube-cli channels --json # machine-readable with subscriber counts
+ scripts/peertube comments --id <UUID> # GET /videos/{id}/comment-threads
+ scripts/peertube comments --id <UUID> --limit 30 --json
```
- Shows: display name, channel handle (@name), video count, subscriber count.
+ ### channels / channel / account — creators (anonymous)
- ### me — Your profile
+ ```bash
+ scripts/peertube channels --limit 20 --json # instance channel list
+ scripts/peertube channel --handle framasoft@framatube.org # name or name@host
+ scripts/peertube account --name chocobozzz@framatube.org
+ ```
+ `channel` shows metadata plus the channel's uploads (offset-paginated).
+
+ ### me / my-videos — your account (requires login)
+
```bash
- peertube-cli me # your account stats
- peertube-cli me --json # machine-readable
+ scripts/peertube me --json | jq '.role.label'
+ scripts/peertube my-videos --limit 50 --json
```
- Shows: username, role, video count, view count. Requires authentication.
+ ### login / logout — OAuth2 session management
- ## Global Flags
+ ```bash
+ scripts/peertube login --username <NAME> --prompt # hidden prompt
+ echo "<PASSWORD>" | scripts/peertube login --username <NAME> --password-stdin
+ scripts/peertube login --username <NAME> --otp <CODE> # 2FA-enabled accounts
+ scripts/peertube logout # revoke server-side + delete file
+ ```
- All flags work in any position:
+ ## Global flags
```bash
- peertube-cli --json videos # flag before subcommand
- peertube-cli videos --json # flag after subcommand
- peertube-cli --dry-run search --query "test" # preview (no API call)
- peertube-cli --quiet videos # suppress non-essential output
- peertube-cli --verbose channels # detailed logging
+ scripts/peertube --json videos # flag before or after the subcommand
+ scripts/peertube videos --json
+ scripts/peertube --dry-run search --query test # request plan, zero network
+ scripts/peertube --verbose videos --limit 2 # trace requests on stderr
+ scripts/peertube --server https://tilvids.com server # per-invocation instance override
```
+ `--dry-run` emits `{"dry_run": true, "method", "path", "params"}` (login adds
+ `form_fields` names only, never values) — use it to verify a jq chain before running it
+ live. `--help` and `--dry-run` never require credentials.
+
+ ## Pipeline recipes
+
+ ### Search, then inspect the top hit
+
+ ```bash
+ scripts/peertube search --query "linux" --limit 5 --json | jq -r '.videos[0].uuid'
+ scripts/peertube video --id "$(scripts/peertube search -q linux --limit 1 --json | jq -r '.videos[0].uuid')" --json
+ ```
+
+ ### Page through a channel's uploads
+
+ ```bash
+ scripts/peertube channel --handle framasoft@framatube.org --limit 100 --offset 0 --json | jq -r '.videos[].name'
+ # loop: advance --offset by the returned count until you reach .total (no page param exists)
+ ```
+
+ ### Instance report card
+
+ ```bash
+ scripts/peertube server --json | jq '{name: .instance.name, videos: .stats.totalLocalVideos, users: .stats.totalUsers, views: .stats.totalLocalVideoViews}'
+ ```
+
+ ### Log in, check quota, log out
+
+ ```bash
+ scripts/peertube login --username <NAME> --prompt
+ scripts/peertube me --json | jq '{username, role: .role.label, quota_bytes: .videoQuota}'
+ scripts/peertube logout
+ ```
+
+ ## JSON and jq
+
+ `--json` output keys are stable snake_case wrappers around raw API objects: `videos`
+ (the API's `{total, data}` list objects), `channels`, `threads` (+ `total_not_deleted`),
+ `instance` + `stats`, `channel`, `dry_run`/`method`/`path`/`params` for plans. Video
+ objects keep PeerTube's own field names — `uuid`, `shortUUID`, `name`, `duration`
+ (seconds), `views`, `publishedAt`, `account{name,displayName,host}`,
+ `channel{name,displayName,host}` — so jq selectors transfer directly to raw `curl`
+ against `/api/v1`. Example: `jq -r '.videos[] | [.name, .views, .channel.displayName] | @tsv'`.
+
## Known Gotchas
- - **Set PEERTUBE_SERVER first** — Without this env var, the CLI defaults to `https://your-instance.example.com` (which won't resolve). Always export the correct instance URL.
- - **Authentication is required for most commands** — `server` and public video browsing work without auth. `me`, `channels`, and personal video lists require a valid OAuth token. Use `--dry-run` to preview without auth.
- - **Token is persisted automatically** — After `auth login`, the token is saved to `~/.config/peertube-cli/token.json`. No need to login again unless the token expires. Delete this file to force re-login.
- - **Token expiry** — PeerTube OAuth2 tokens have a configurable expiry (default ~24h). Expired tokens cause 401 errors. Re-run `auth login` to refresh.
- - **Cross-instance search** — `search --query` searches across the fediverse, not just the local instance. Results may include videos from remote instances.
- - **API pagination** — PeerTube uses offset-based pagination. The `--limit` flag controls the page size (default: 12 for videos, 15 for channels).
- - **Rate limits** — PeerTube instances have configurable rate limits. The CLI does not auto-retry on 429 responses.
+ - **Instances are independent (federated, not one API)** — accounts, tokens, rules,
+ enabled features, and catalogs differ per instance. A token from instance A 401s on
+ instance B; the CLI keys the token file by server URL. Content federated *onto* an
+ instance still belongs to its origin (`channel.host`, video `url`).
+ - **Search scope is two different things** — `searchTarget=local` searches the
+ instance's own catalog; `search-index` (or SepiaSearch's base URL) searches the
+ fediverse via an external index. Omitting `searchTarget` gives the instance's own
+ scope on current servers, not the fediverse. The bundled CLI is instance-local unless
+ you point it at sepiasearch.org.
+ - **`page` does not exist** — collections paginate with `start`/`count` (max 100).
+ Clients sending `page=` silently re-read the first page forever.
+ - **The comments route is `/comment-threads`** (hyphenated) — `/comments` and
+ `/commentthreads` are not routes (they 400 on current servers).
+ - **Instance metadata paths are mixed** — stats at `/server/stats` (operation titled
+ "instance stats"), about at `/config/about`, config at `/config`. No
+ `/instance/*` metadata paths exist.
+ - **Production masks `client_secret`** — `oauth-clients/local` answers
+ `"********************************"` on current production instances; a token request
+ with the masked value 400s. The CLI detects it and explains the front-end-asset
+ workaround. `response_type=code` appears in old quick-start curls but is not part of
+ the current token schema — the CLI omits it.
+ - **Token lifetimes are instance-configurable** — read `expires_in` per response; the
+ CLI persists the absolute `expires_at` and refreshes automatically. Store tokens
+ owner-only, never commit them, revoke on logout (deleting the file alone leaves the
+ session live).
+ - **2FA needs an OTP header** — `x-peertube-otp` on the token request; the CLI maps a
+ bare 401 to "pass --otp".
+ - **Rate limits** — default 50 calls/10 s per IP (token endpoint tighter); on 429 read
+ `Retry-After` and back off. Errors use RFC7807 `application/problem+json` bodies, and
+ unknown routes answer 400 (not 404) — read the body.
+ - **`duration` is seconds**; ids are triple (`id`, `uuid`, `shortUUID` — all accepted by
+ detail endpoints); `role` is an object `{id, label}`; `videoQuota` is bytes.
+ - **Anonymous vs authed** — browsing/search/comments/instance-info need no token;
+ `/users/me*` and mutations always do.
- ## References
+ ## When to use
- - [scripts/peertube-cli](scripts/peertube-cli) — The CLI binary. Built following the cli-builder patterns: `--json`, `--dry-run`, `--quiet`, `--verbose`, dual-output via `emit()`, lazy auth, config file persistence.
- - [PeerTube API Reference](https://docs.joinpeertube.org/api/reference) — Official API reference.
- - [JoinPeerTube.org](https://joinpeertube.org/) — Find instances and learn about the federated video platform.
+ Use this skill for read-only interaction with PeerTube instances: browsing and filtering
+ videos, instance-local or fediverse-wide search (via SepiaSearch), video detail and
+ comments, channel/account exploration, instance stats, and managing your own account
+ session with OAuth2 (login, profile, my videos, logout).
+
+ ## When not to use
+
+ Do not use this skill for YouTube, Vimeo, or other platform uploads or any video
+ editing/transcoding (route to those platforms' own tooling and ffmpeg); for installing,
+ hosting, or administering a PeerTube server (instance administration is out of scope —
+ the bundled CLI is read-only plus login/logout); or for generic ActivityPub/Mastodon
+ federation questions (use a Mastodon or ActivityPub skill).
+
+ ## Reference Files
+
+ | File | Use it for |
+ | ---- | ---------- |
+ | [references/auth-and-tokens.md](references/auth-and-tokens.md) | OAuth2 flow (oauth-clients/local, password grant), secret masking, refresh/revocation, token-file hygiene, wire error signatures |
+ | [references/search-and-discovery.md](references/search-and-discovery.md) | searchTarget local vs search-index, SepiaSearch semantics, search parameters and sorts |
+ | [references/endpoint-catalog.md](references/endpoint-catalog.md) | Every read endpoint's parameters, response shapes, pagination, rate limits |
+ | [references/gotchas-field-guide.md](references/gotchas-field-guide.md) | Symptom → cause → fix table for every failure signature and version drift |
+ | [references/worked-recipes.md](references/worked-recipes.md) | Multi-step CLI/jq workflows, raw curl auth chain, jq processing patterns |
+
+ ## Available Scripts and Prerequisites
+
+ - `scripts/peertube` — the bundled Python CLI (`--json`, `--dry-run`, `--verbose`,
+ `--server` override). Imports only the standard library and `requests`.
+ - `scripts/test_peertube.py` — offline test suite (pytest + unittest compatible); all
+ HTTP is mocked, zero network egress.
+ - Requires Python 3.8+ and `requests`. Any reachable PeerTube instance (or SepiaSearch)
+ works; no credentials exist or are required by default. No service is started by this
+ skill.