twentythree-skills 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -0
- package/bin/add.js +103 -0
- package/package.json +46 -0
- package/skills/SKILL.md +211 -0
- package/skills/reference/action.md +233 -0
- package/skills/reference/analytics.md +337 -0
- package/skills/reference/app.md +160 -0
- package/skills/reference/audience.md +377 -0
- package/skills/reference/category.md +123 -0
- package/skills/reference/collector.md +103 -0
- package/skills/reference/comment.md +225 -0
- package/skills/reference/openupload.md +138 -0
- package/skills/reference/player.md +192 -0
- package/skills/reference/poll.md +174 -0
- package/skills/reference/presentation.md +99 -0
- package/skills/reference/protection.md +131 -0
- package/skills/reference/session.md +98 -0
- package/skills/reference/setting.md +115 -0
- package/skills/reference/site.md +94 -0
- package/skills/reference/spot.md +188 -0
- package/skills/reference/tag.md +93 -0
- package/skills/reference/thumbnail.md +224 -0
- package/skills/reference/user.md +216 -0
- package/skills/reference/video.md +631 -0
- package/skills/reference/webhook.md +151 -0
- package/skills/reference/webinar.md +1371 -0
- package/skills/workflows/upload-and-publish.md +146 -0
- package/skills/workflows/webinar-lifecycle.md +209 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upload-and-publish
|
|
3
|
+
description: Upload a video file, set metadata, and publish it on TwentyThree.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Upload and Publish a Video
|
|
7
|
+
|
|
8
|
+
> Complete sequence for uploading a video file, setting metadata, and making it publicly visible.
|
|
9
|
+
> All commands use `--json` — capture IDs from the `data.photo_id` field of upload responses and `data.id` for other responses.
|
|
10
|
+
|
|
11
|
+
> See [`reference/video.md`](../reference/video.md) for exhaustive flag details and [`reference/category.md`](../reference/category.md) for category selection.
|
|
12
|
+
|
|
13
|
+
## Prerequisites
|
|
14
|
+
|
|
15
|
+
- Auth scope required: **write**
|
|
16
|
+
- Run `twentythree auth credentials` if not already configured.
|
|
17
|
+
- Confirm auth: `twentythree auth status --json`
|
|
18
|
+
- Chunked upload is automatic — `twentythree video upload` handles chunking internally (see `reference/video.md` §video upload).
|
|
19
|
+
|
|
20
|
+
## Steps
|
|
21
|
+
|
|
22
|
+
### 1. (Optional) List categories to find a target category ID
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
twentythree category list --json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Expected output shape: `{ data: [ { id, title, description, hidden }, ... ] }`
|
|
29
|
+
Capture: `data[n].id` of the desired row as `category_id`
|
|
30
|
+
On failure:
|
|
31
|
+
- `401 Unauthorized` → run `twentythree auth status --json` to confirm credentials
|
|
32
|
+
- Empty list → confirm workspace has categories; create one with `twentythree category create --title "…" --json`
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### 2. Upload the video
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
twentythree video upload ./video.mp4 --title "Product Demo" --category-id <category_id> --json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Expected output shape: `{ ok: true, data: { photo_id, tree_id, token } }`
|
|
43
|
+
Capture:
|
|
44
|
+
- `data.photo_id` as `video_id`
|
|
45
|
+
- Construct admin URL as: `https://<domain>/manage/video/<data.photo_id>`
|
|
46
|
+
(surface this to the user — the CLI prints it on stdout but it is not in the JSON data object)
|
|
47
|
+
|
|
48
|
+
On failure:
|
|
49
|
+
- Network error or `401` → run `twentythree auth status` and `twentythree doctor`
|
|
50
|
+
- Upload stalls → retry; chunked upload resumes automatically (see `reference/video.md` for `--chunk-size` / `--concurrency` tuning)
|
|
51
|
+
- `413 Payload Too Large` → the file exceeds workspace quota; check `twentythree site get --include-quota --json`
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
### 3. (Optional) Set additional metadata
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
twentythree video update <video_id> --description "Launch video for Q2 release" --tags "product q2 launch" --json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Expected output shape: `{ ok: true, data: { photo_id, title, description, ... } }`
|
|
62
|
+
Capture: none (fire-and-forget update — verify with `twentythree video get <video_id> --json` if needed)
|
|
63
|
+
On failure:
|
|
64
|
+
- `403 Forbidden` → confirm auth scope is `write`, not `read`
|
|
65
|
+
- `404 Not Found` → confirm `video_id` is correct and video exists (`twentythree video get <video_id> --json`)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### 4. (Optional) Set a custom thumbnail frame
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
twentythree video frame <video_id> --time 10 --json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Expected output shape: `{ data: { id, thumbnail_url } }`
|
|
76
|
+
Capture: none
|
|
77
|
+
On failure:
|
|
78
|
+
- `400 Invalid Time` → ensure `--time` is less than video duration (check via `twentythree video get <video_id> --json`)
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### 5. (Optional) Wait for transcoding to complete
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
twentythree video transcoding-progress <video_id> --json
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Expected output shape: `{ data: { status, progress } }`
|
|
89
|
+
Capture: `data.status` — must be `complete` before publishing
|
|
90
|
+
On failure:
|
|
91
|
+
- Status stuck at `processing` for >10 minutes → contact support; do NOT publish
|
|
92
|
+
- Status `failed` → check the video file; re-upload if corrupt
|
|
93
|
+
|
|
94
|
+
Polling pattern:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
while true; do
|
|
98
|
+
STATUS=$(twentythree video transcoding-progress <video_id> --json | jq -r '.data.status')
|
|
99
|
+
if [ "$STATUS" = "complete" ]; then break; fi
|
|
100
|
+
sleep 30
|
|
101
|
+
done
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### 6. Publish
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
twentythree video update <video_id> --publish --json
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Expected output shape: `{ data: { id, published: true } }`
|
|
113
|
+
Capture: confirm `data.published` is `true`
|
|
114
|
+
On failure:
|
|
115
|
+
- `403 Forbidden` → confirm auth scope is `write`
|
|
116
|
+
- Publish fails silently → run `twentythree video get <video_id> --json` and check `published` field
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Error Handling
|
|
121
|
+
|
|
122
|
+
| Step | Failure | What to check |
|
|
123
|
+
|------|---------|---------------|
|
|
124
|
+
| 1 | Empty category list | `twentythree category create --title "…" --json` to create one |
|
|
125
|
+
| 1 | `401 Unauthorized` | `twentythree auth status --json` to confirm credentials |
|
|
126
|
+
| 2 | Upload auth/network error | `twentythree auth status --json`, `twentythree doctor` |
|
|
127
|
+
| 2 | Quota exceeded | `twentythree site get --include-quota --json` |
|
|
128
|
+
| 3 | 403 Forbidden | Confirm auth scope is `write` |
|
|
129
|
+
| 3 | 404 Not Found | `twentythree video get <video_id> --json` to confirm video exists |
|
|
130
|
+
| 4 | Invalid time | `--time` must be less than duration from `video get` |
|
|
131
|
+
| 5 | Transcoding stuck | Poll `transcoding-progress` after 30s; contact support after 10 min |
|
|
132
|
+
| 5 | Status `failed` | Check video file integrity; re-upload if corrupt |
|
|
133
|
+
| 6 | 403 Forbidden | Confirm auth scope is `write` |
|
|
134
|
+
| 6 | Publish fails silently | `twentythree video get <video_id> --json` to check `published` field |
|
|
135
|
+
|
|
136
|
+
## Notes
|
|
137
|
+
|
|
138
|
+
- All 6 steps can be scripted in sequence; only Steps 2 and 6 are strictly required (1, 3, 4, 5 are optional).
|
|
139
|
+
- For a minimal end-to-end sequence: pass `--publish` directly to the upload command:
|
|
140
|
+
```bash
|
|
141
|
+
twentythree video upload ./video.mp4 --title "Demo" --publish --json
|
|
142
|
+
```
|
|
143
|
+
This is valid but skips the optional metadata, frame, and transcoding-check steps.
|
|
144
|
+
- The admin URL from Step 2 opens the video's admin edit page — surface this to the user so they can review or make manual edits. Construct it as `https://<domain>/manage/video/<data.photo_id>` (it is printed on stdout by the CLI but is not included in the JSON data object).
|
|
145
|
+
- `--category-id` accepts a comma-separated list of IDs to assign to multiple categories simultaneously.
|
|
146
|
+
- After a successful publish, use `twentythree video get <video_id> --json` to confirm the `published` field is `true` before reporting success to the user.
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: webinar-lifecycle
|
|
3
|
+
description: Create, configure, run, record, and archive a live webinar end-to-end.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow: Webinar Lifecycle
|
|
7
|
+
|
|
8
|
+
> Complete sequence from creating a webinar through archiving it after the session ends.
|
|
9
|
+
> All commands use `--json` — capture IDs from the `data.id` field of each response.
|
|
10
|
+
> CLI `webinar` maps to API `live` — see `reference/webinar.md` §Terminology Notes.
|
|
11
|
+
|
|
12
|
+
> See [`reference/webinar.md`](../reference/webinar.md) for exhaustive flag details on every command referenced below.
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
- Auth scope required: **write** (create, update, upload-image, recording, publishing)
|
|
17
|
+
- Some read-only steps (room connect, clips) accept `read` scope
|
|
18
|
+
- Run `twentythree auth credentials` if not already configured.
|
|
19
|
+
- Confirm auth: `twentythree auth status --json`
|
|
20
|
+
- NOTE: There is no `webinar get` command — to retrieve webinar details, use `webinar list --search "<title>" --json` (see `reference/webinar.md`).
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
### 1. Create the webinar
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
twentythree webinar create --title "Q2 Town Hall" --live-date "2026-05-15T16:00:00Z" --description "Quarterly update" --json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Expected output shape: `{ data: { id, admin_url } }`
|
|
31
|
+
Capture:
|
|
32
|
+
- `data.id` as `webinar_id`
|
|
33
|
+
- `data.admin_url` as `admin_url` (surface to the user — always print ID + admin URL after create)
|
|
34
|
+
|
|
35
|
+
On failure:
|
|
36
|
+
- `400 Invalid date` → `--live-date` must be ISO 8601 (e.g. `2026-05-15T16:00:00Z`)
|
|
37
|
+
- `401 Unauthorized` → run `twentythree auth status --json`
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
### 2. (Optional) Add agenda sections
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
twentythree webinar section add <webinar_id> --title "Intro" --start-time 0 --json
|
|
45
|
+
twentythree webinar section add <webinar_id> --title "Q&A" --start-time 1800 --json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Expected output shape: `{ data: { id, title, start_time } }`
|
|
49
|
+
Capture: `data.id` as `section_id` if you intend to update or remove this section later; otherwise none
|
|
50
|
+
On failure:
|
|
51
|
+
- `404 Not Found` → confirm `webinar_id` exists (`twentythree webinar list --search "<title>" --json`)
|
|
52
|
+
- Validation error → confirm `--start-time` is in seconds, not mm:ss format
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### 3. (Optional) Add speakers
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
twentythree webinar speaker add <webinar_id> --name "Jane Doe" --email jane@example.com --title "CTO" --json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Expected output shape: `{ data: { id, name, role } }`
|
|
63
|
+
Capture: `data.id` as `speaker_id` if you need to update or remove this speaker later
|
|
64
|
+
On failure:
|
|
65
|
+
- Missing required flag → run `twentythree webinar speaker add --agent` to see the complete flag list
|
|
66
|
+
- `404 Not Found` → confirm `webinar_id` exists
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### 4. (Optional) Upload a thumbnail image
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
twentythree webinar upload-image <webinar_id> ./thumb.jpg --type thumbnail --json
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Expected output shape: none (upload-image returns no JSON body — success is confirmed by exit code 0)
|
|
77
|
+
Capture: none (image is attached to the webinar automatically)
|
|
78
|
+
On failure:
|
|
79
|
+
- `413 Payload Too Large` → resize image; chunked upload is automatic but workspace size limits still apply
|
|
80
|
+
- `401 Unauthorized` → run `twentythree auth status --json`
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### 5. Publish the webinar (make visible to registrants)
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
twentythree webinar update <webinar_id> --publish --json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Expected output shape: `{ data: { id, published: true } }`
|
|
91
|
+
Capture: confirm `data.published` is `true`
|
|
92
|
+
On failure:
|
|
93
|
+
- `403 Forbidden` → auth scope `write` required
|
|
94
|
+
- Publish fails silently → run `twentythree webinar list --search "<title>" --json` and check the `published` field
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
### 6. Get room connection info (when going live)
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
twentythree webinar room connect <webinar_id> --json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Expected output shape: `{ data: { stream_key, room_url } }`
|
|
105
|
+
Capture:
|
|
106
|
+
- `data.stream_key` as `stream_key` — pass to your broadcasting software (OBS, Zoom, etc.)
|
|
107
|
+
- `data.room_url` as `room_url` — pass to moderators who join the room
|
|
108
|
+
|
|
109
|
+
On failure:
|
|
110
|
+
- Webinar status is `previous` → room connection unavailable for archived webinars; run `twentythree webinar update <webinar_id> --status upcoming --json` to re-open
|
|
111
|
+
- `404 Not Found` → confirm `webinar_id` is correct
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### 7. (Optional) Start recording once the live session is active
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
twentythree webinar recording start <webinar_id> --json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Expected output shape: `{ data: {} }` (recording start returns minimal output; confirm via `recording status`)
|
|
122
|
+
Capture: none (recording is attached to the webinar; monitor via `webinar recording status`)
|
|
123
|
+
On failure:
|
|
124
|
+
- `409 Conflict` → recording already in progress; run `twentythree webinar recording status <webinar_id> --json` to check
|
|
125
|
+
- `403 Forbidden` → auth scope `write` required
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### 8. Stop recording (after session ends)
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
twentythree webinar recording stop <webinar_id> --json
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Expected output shape: `{ data: {} }` (recording stop returns minimal output; clip processing begins asynchronously)
|
|
136
|
+
Capture: none
|
|
137
|
+
On failure:
|
|
138
|
+
- `409 Conflict` → no recording in progress; confirm with `twentythree webinar recording status <webinar_id> --json`
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### 9. Check recording status and wait for clips
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
twentythree webinar recording status <webinar_id> --json
|
|
146
|
+
twentythree webinar clips <webinar_id> --json
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Expected output shape:
|
|
150
|
+
- `recording status`: `{ data: { status, ... } }` — check `data.status` for `processing` or `complete`
|
|
151
|
+
- `webinar clips`: `{ data: [ { id, title, duration, ... } ] }` — array of clip objects; empty while still processing
|
|
152
|
+
|
|
153
|
+
Capture:
|
|
154
|
+
- `recording status` `data.status` — must be `complete` before clips are fully available
|
|
155
|
+
- `webinar clips` array — each element is a clip with an `id` you can use with `twentythree video` commands
|
|
156
|
+
|
|
157
|
+
On failure:
|
|
158
|
+
- Clips array empty immediately after `stop` → normal; recording processing takes several minutes
|
|
159
|
+
- Clips still empty after 10+ minutes → contact support
|
|
160
|
+
|
|
161
|
+
Polling pattern (wait for at least one clip to be available):
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
while true; do
|
|
165
|
+
CLIPS=$(twentythree webinar clips <webinar_id> --json | jq '.data | length')
|
|
166
|
+
if [ "$CLIPS" -gt 0 ]; then break; fi
|
|
167
|
+
sleep 60
|
|
168
|
+
done
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
### 10. (Optional) Archive — mark as previous
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
twentythree webinar update <webinar_id> --status previous --json
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Expected output shape: `{ data: { id, status: "previous" } }`
|
|
180
|
+
Capture: none
|
|
181
|
+
On failure:
|
|
182
|
+
- `400 Bad Request` → check current status; `recording stop` must be called before archiving a live session
|
|
183
|
+
- Some status transitions may be blocked: confirm `recording status` is not `recording` before archiving
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Error Handling
|
|
188
|
+
|
|
189
|
+
| Step | Failure | What to check |
|
|
190
|
+
|------|---------|---------------|
|
|
191
|
+
| 1 | Invalid date | `--live-date` must be ISO 8601 (e.g. `2026-05-15T16:00:00Z`) |
|
|
192
|
+
| 1 | `401 Unauthorized` | `twentythree auth status --json` to confirm credentials |
|
|
193
|
+
| 2-3 | Missing required flags | Run `twentythree webinar <subtopic> <cmd> --agent` to enumerate all flags |
|
|
194
|
+
| 2-3 | `404 Not Found` | `webinar_id` invalid; `twentythree webinar list --search "<title>" --json` to find it |
|
|
195
|
+
| 5 | Publish 403 | Confirm auth scope is `write` |
|
|
196
|
+
| 6 | Room connection blocked | Webinar status must be `upcoming` or `live`, not `previous` |
|
|
197
|
+
| 7 | Recording 409 Conflict | Already recording; `twentythree webinar recording status <webinar_id> --json` first |
|
|
198
|
+
| 8 | Stop 409 Conflict | No recording in progress; verify with `recording status` |
|
|
199
|
+
| 9 | Clips empty | Processing can take 10+ minutes after `recording stop`; poll every 60s |
|
|
200
|
+
| 10 | Status transition blocked | Confirm `recording stop` was called; check `recording status` is not `recording` |
|
|
201
|
+
|
|
202
|
+
## Notes
|
|
203
|
+
|
|
204
|
+
- Steps 2-4 (sections, speakers, thumbnail) are optional but improve viewer experience.
|
|
205
|
+
- Step 6 (`room connect`) returns credentials for a third-party broadcaster. Agents should NOT attempt to stream content themselves — pass the `stream_key` and `room_url` to the user.
|
|
206
|
+
- Steps 7-8 (recording start/stop) are optional. If you skip them, no clips will be generated after the session.
|
|
207
|
+
- Step 9's polling loop can be replaced by subscribing to the `recording.completed` webhook event (see `reference/webhook.md`).
|
|
208
|
+
- Use `twentythree webinar list --search "<title>" --json` as the canonical way to retrieve webinar details — there is no `webinar get` command.
|
|
209
|
+
- Clips generated from recording are standard video assets. After they appear in `webinar clips`, you can manage them with the full `video` command set (e.g. `twentythree video update <clip_id> --publish --json`).
|