youtube-kit 0.2.0__tar.gz
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.
- youtube_kit-0.2.0/LICENSE +21 -0
- youtube_kit-0.2.0/PKG-INFO +174 -0
- youtube_kit-0.2.0/README.md +138 -0
- youtube_kit-0.2.0/pyproject.toml +84 -0
- youtube_kit-0.2.0/pyproject.toml.orig +64 -0
- youtube_kit-0.2.0/src/youtube_kit/__init__.py +0 -0
- youtube_kit-0.2.0/src/youtube_kit/cli.py +217 -0
- youtube_kit-0.2.0/src/youtube_kit/core/__init__.py +36 -0
- youtube_kit-0.2.0/src/youtube_kit/core/auth.py +103 -0
- youtube_kit-0.2.0/src/youtube_kit/core/client.py +62 -0
- youtube_kit-0.2.0/src/youtube_kit/core/config.py +59 -0
- youtube_kit-0.2.0/src/youtube_kit/core/errors.py +118 -0
- youtube_kit-0.2.0/src/youtube_kit/core/guard.py +50 -0
- youtube_kit-0.2.0/src/youtube_kit/core/models.py +228 -0
- youtube_kit-0.2.0/src/youtube_kit/core/operation.py +102 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/__init__.py +3 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/_common.py +83 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/analytics.py +107 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/branding.py +276 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/channels.py +112 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/comments.py +205 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/playlists.py +282 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/search.py +72 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/subscriptions.py +77 -0
- youtube_kit-0.2.0/src/youtube_kit/core/ops/videos.py +332 -0
- youtube_kit-0.2.0/src/youtube_kit/core/pagination.py +41 -0
- youtube_kit-0.2.0/src/youtube_kit/core/parse.py +144 -0
- youtube_kit-0.2.0/src/youtube_kit/core/progress.py +29 -0
- youtube_kit-0.2.0/src/youtube_kit/mcp_server.py +84 -0
- youtube_kit-0.2.0/src/youtube_kit/py.typed +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eugene Kosharnyi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: youtube-kit
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: A CLI (ytk) and MCP server for the YouTube Data and Analytics APIs, built for agents and humans.
|
|
5
|
+
Keywords: youtube,youtube-data-api,youtube-analytics,cli,mcp,model-context-protocol,agents
|
|
6
|
+
Author: Eugene Kosharnyi
|
|
7
|
+
Author-email: Eugene Kosharnyi <eugene.kosharnyi@gmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Multimedia :: Video
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Dist: cyclopts>=4.22,<5
|
|
23
|
+
Requires-Dist: fastmcp>=4.1,<5
|
|
24
|
+
Requires-Dist: google-api-python-client>=2.199.0
|
|
25
|
+
Requires-Dist: google-auth>=2.56
|
|
26
|
+
Requires-Dist: google-auth-oauthlib>=1.4.0
|
|
27
|
+
Requires-Dist: httplib2>=0.22
|
|
28
|
+
Requires-Dist: platformdirs>=4.11
|
|
29
|
+
Requires-Dist: pydantic>=2.13,<3
|
|
30
|
+
Requires-Python: >=3.12
|
|
31
|
+
Project-URL: Homepage, https://github.com/eukosh/youtube-kit
|
|
32
|
+
Project-URL: Documentation, https://github.com/eukosh/youtube-kit#readme
|
|
33
|
+
Project-URL: Issues, https://github.com/eukosh/youtube-kit/issues
|
|
34
|
+
Project-URL: Changelog, https://github.com/eukosh/youtube-kit/blob/main/CHANGELOG.md
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# youtube-kit
|
|
38
|
+
|
|
39
|
+
[](https://github.com/eukosh/youtube-kit/actions/workflows/ci.yml)
|
|
40
|
+
[](https://pypi.org/project/youtube-kit/)
|
|
41
|
+
[](https://pypi.org/project/youtube-kit/)
|
|
42
|
+
[](https://github.com/eukosh/youtube-kit/blob/main/LICENSE)
|
|
43
|
+
|
|
44
|
+
Your YouTube channel from the terminal and from AI agents. `ytk` is a CLI over the YouTube Data and Analytics APIs that prints JSON, and `ytk mcp` serves the same operations to MCP clients.
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
ytk channel get @mkbhd | jq '{title, subscribers: .stats.subscribers}'
|
|
48
|
+
ytk analytics --by video --since 90d --limit 5 # your top videos of the last 90 days
|
|
49
|
+
ytk comment list --status held # comments waiting for review on your channel
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- **Built for agents, pleasant for people.** One JSON document on stdout, structured errors on stderr, a distinct exit code per failure. Coding agents with a shell use it through a short [skill](#use-it-from-an-agent) that they load only when a YouTube task comes up.
|
|
53
|
+
- **One core, two surfaces.** Every operation is a typed function. The CLI and the MCP server are thin adapters over it, and a test fails if either one misses an operation.
|
|
54
|
+
- **Safe deletes.** Deleting needs a confirmation that names the exact target, and popular or long-public videos can't be deleted at all. [Details below.](#deleting)
|
|
55
|
+
- **Quota-aware.** Each command's `--help` (and each MCP tool description) states its quota cost.
|
|
56
|
+
|
|
57
|
+
## What it covers
|
|
58
|
+
|
|
59
|
+
| Area | Commands |
|
|
60
|
+
|---|---|
|
|
61
|
+
| Search | `search` across videos, channels and playlists |
|
|
62
|
+
| Videos | get, upload (resumable), update, thumbnail, processing status, rate, delete |
|
|
63
|
+
| Playlists | list, get, items, create, update, thumbnail, add, remove, move, delete |
|
|
64
|
+
| Comments | list (including held for review and likely spam), replies, post, reply, edit, delete, approve, hold, reject and ban |
|
|
65
|
+
| Channel | get, recent activity, about info, banner, watermark, home page sections |
|
|
66
|
+
| Subscriptions | list, subscribe, unsubscribe |
|
|
67
|
+
| Analytics | totals or breakdowns by day, month, video, country, device, traffic source, age, gender and more |
|
|
68
|
+
|
|
69
|
+
`ytk --help` lists everything; the [skill](https://github.com/eukosh/youtube-kit/blob/main/skills/youtube/SKILL.md) has the full command map.
|
|
70
|
+
|
|
71
|
+
## Install
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
uv tool install youtube-kit # or: pipx install youtube-kit
|
|
75
|
+
ytk --help
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Or run it without installing: `uvx --from youtube-kit ytk --help`. Needs Python 3.12 or newer.
|
|
79
|
+
|
|
80
|
+
## Credentials
|
|
81
|
+
|
|
82
|
+
Public data (search, videos, channels, playlists, comments) works with an API key. Anything on your own channel (uploads, edits, deletes, comment moderation, branding, subscriptions, ratings, analytics) needs an OAuth login.
|
|
83
|
+
|
|
84
|
+
1. In the [Google Cloud Console](https://console.cloud.google.com), create a project and enable **YouTube Data API v3**, plus **YouTube Analytics API** for `ytk analytics`.
|
|
85
|
+
2. **API key** for public data: create one and `export YOUTUBE_API_KEY=...`. Without a key, `ytk` uses your OAuth login for public data too.
|
|
86
|
+
3. **OAuth** for your channel:
|
|
87
|
+
1. Configure the OAuth consent screen (user type *External*) and add your Google account as a test user.
|
|
88
|
+
2. Create an OAuth client ID of type *Desktop app*, download its JSON, and save it where `ytk auth status` says `client_secrets_file` lives.
|
|
89
|
+
3. Run `ytk auth login`. It opens a browser and stores a token that the CLI and the MCP server share.
|
|
90
|
+
|
|
91
|
+
> [!NOTE]
|
|
92
|
+
> While the consent screen is in *Testing* status, Google expires the login after 7 days and you need to run `ytk auth login` again. To keep it, set the publishing status to *In production*. Google then shows an "unverified app" warning at login, which is expected for your own client; continue past it.
|
|
93
|
+
|
|
94
|
+
Credentials and `config.toml` live in the user config directory (`~/Library/Application Support/youtube-kit/` on macOS, `~/.config/youtube-kit/` on Linux); `ytk auth status` prints the exact paths. These environment variables override them:
|
|
95
|
+
|
|
96
|
+
| Variable | Purpose |
|
|
97
|
+
|---|---|
|
|
98
|
+
| `YOUTUBE_API_KEY` | API key for public data |
|
|
99
|
+
| `YOUTUBE_CLIENT_SECRETS` | Path to the OAuth client JSON |
|
|
100
|
+
| `YOUTUBE_TOKEN_FILE` | Path to the stored login |
|
|
101
|
+
| `YOUTUBE_CONFIG_FILE` | Path to `config.toml` (delete limits) |
|
|
102
|
+
|
|
103
|
+
## Use it from an agent
|
|
104
|
+
|
|
105
|
+
**Shell agents (Claude Code, Codex and others)** use the CLI through the skill. For Claude Code:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
mkdir -p ~/.claude/skills/youtube
|
|
109
|
+
curl -fsSL https://raw.githubusercontent.com/eukosh/youtube-kit/main/skills/youtube/SKILL.md \
|
|
110
|
+
-o ~/.claude/skills/youtube/SKILL.md
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**MCP clients** run the server with `ytk mcp`. The examples below use `uvx`, which comes with [uv](https://docs.astral.sh/uv/). For Claude Code:
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
claude mcp add youtube -- uvx --from youtube-kit ytk mcp
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
For clients configured with JSON (Claude Desktop, Cursor and others):
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"mcpServers": {
|
|
124
|
+
"youtube": {
|
|
125
|
+
"command": "uvx",
|
|
126
|
+
"args": ["--from", "youtube-kit", "ytk", "mcp"],
|
|
127
|
+
"env": { "YOUTUBE_API_KEY": "..." }
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The API key is optional; without it the server uses your `ytk auth login` token.
|
|
134
|
+
|
|
135
|
+
## Output and exit codes
|
|
136
|
+
|
|
137
|
+
Every command prints one JSON document on stdout, with null fields left out. On failure stdout stays empty and stderr gets:
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{"error": {"type": "not_found", "message": "Video abc123def45 not found."}}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The exit code names the type: 2 bad input, 3 not found, 4 not authorized, 5 quota exceeded, 6 forbidden, 7 network, 8 confirmation required, 9 protected, 10 timeout, 1 anything else. The [skill](https://github.com/eukosh/youtube-kit/blob/main/skills/youtube/SKILL.md#output-contract) says what an agent should do about each.
|
|
144
|
+
|
|
145
|
+
Video, channel and playlist arguments take IDs or pasted URLs; channels also take an `@handle`.
|
|
146
|
+
|
|
147
|
+
## Deleting
|
|
148
|
+
|
|
149
|
+
Agents make mistakes, so deleting videos, playlists and comments is guarded:
|
|
150
|
+
|
|
151
|
+
- **Two steps.** The first call deletes nothing. At a terminal you get a `[y/N]` prompt. An agent gets exit 8 with a description of the target and must run the command again with `--confirm <id>`, so the approval always names the exact thing being deleted.
|
|
152
|
+
- **Damage limit.** A video with more than 100 views, or one that is public and was uploaded more than 7 days ago, can't be deleted here at all; use YouTube Studio. The limits live in `config.toml` (`ytk auth status` shows where):
|
|
153
|
+
|
|
154
|
+
```toml
|
|
155
|
+
[delete_protection]
|
|
156
|
+
max_views = 100
|
|
157
|
+
max_public_age_days = 7
|
|
158
|
+
```
|
|
159
|
+
- **Harness approval.** Have your agent ask you before every delete; the skill has a Claude Code permission snippet for it.
|
|
160
|
+
- **Idempotent.** Deleting something that is already gone succeeds with `"already_gone": true`.
|
|
161
|
+
|
|
162
|
+
This stops mistakes, not a determined agent: anything holding your OAuth token can call the API directly.
|
|
163
|
+
|
|
164
|
+
## Quota
|
|
165
|
+
|
|
166
|
+
Google gives each Cloud project 10,000 units a day, resetting at midnight Pacific time. Reads cost 1 unit per request, `search` 100 per page of 50 results, most writes 50 (deletes a couple more, for the lookup and ownership check), and an upload 1,600. Analytics has its own separate quota.
|
|
167
|
+
|
|
168
|
+
## Contributing
|
|
169
|
+
|
|
170
|
+
Bug reports and pull requests are welcome. See [CONTRIBUTING.md](https://github.com/eukosh/youtube-kit/blob/main/CONTRIBUTING.md) for the development setup, [CHANGELOG.md](https://github.com/eukosh/youtube-kit/blob/main/CHANGELOG.md) for what changed, and [ADR 0001](https://github.com/eukosh/youtube-kit/blob/main/docs/adr/0001-shared-core-cli-and-mcp.md) for how the code fits together. Report security issues privately, as described in [SECURITY.md](https://github.com/eukosh/youtube-kit/blob/main/SECURITY.md).
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
[MIT](https://github.com/eukosh/youtube-kit/blob/main/LICENSE). youtube-kit is not affiliated with or endorsed by Google or YouTube. YouTube is a trademark of Google LLC.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# youtube-kit
|
|
2
|
+
|
|
3
|
+
[](https://github.com/eukosh/youtube-kit/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/youtube-kit/)
|
|
5
|
+
[](https://pypi.org/project/youtube-kit/)
|
|
6
|
+
[](https://github.com/eukosh/youtube-kit/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
Your YouTube channel from the terminal and from AI agents. `ytk` is a CLI over the YouTube Data and Analytics APIs that prints JSON, and `ytk mcp` serves the same operations to MCP clients.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
ytk channel get @mkbhd | jq '{title, subscribers: .stats.subscribers}'
|
|
12
|
+
ytk analytics --by video --since 90d --limit 5 # your top videos of the last 90 days
|
|
13
|
+
ytk comment list --status held # comments waiting for review on your channel
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- **Built for agents, pleasant for people.** One JSON document on stdout, structured errors on stderr, a distinct exit code per failure. Coding agents with a shell use it through a short [skill](#use-it-from-an-agent) that they load only when a YouTube task comes up.
|
|
17
|
+
- **One core, two surfaces.** Every operation is a typed function. The CLI and the MCP server are thin adapters over it, and a test fails if either one misses an operation.
|
|
18
|
+
- **Safe deletes.** Deleting needs a confirmation that names the exact target, and popular or long-public videos can't be deleted at all. [Details below.](#deleting)
|
|
19
|
+
- **Quota-aware.** Each command's `--help` (and each MCP tool description) states its quota cost.
|
|
20
|
+
|
|
21
|
+
## What it covers
|
|
22
|
+
|
|
23
|
+
| Area | Commands |
|
|
24
|
+
|---|---|
|
|
25
|
+
| Search | `search` across videos, channels and playlists |
|
|
26
|
+
| Videos | get, upload (resumable), update, thumbnail, processing status, rate, delete |
|
|
27
|
+
| Playlists | list, get, items, create, update, thumbnail, add, remove, move, delete |
|
|
28
|
+
| Comments | list (including held for review and likely spam), replies, post, reply, edit, delete, approve, hold, reject and ban |
|
|
29
|
+
| Channel | get, recent activity, about info, banner, watermark, home page sections |
|
|
30
|
+
| Subscriptions | list, subscribe, unsubscribe |
|
|
31
|
+
| Analytics | totals or breakdowns by day, month, video, country, device, traffic source, age, gender and more |
|
|
32
|
+
|
|
33
|
+
`ytk --help` lists everything; the [skill](https://github.com/eukosh/youtube-kit/blob/main/skills/youtube/SKILL.md) has the full command map.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
uv tool install youtube-kit # or: pipx install youtube-kit
|
|
39
|
+
ytk --help
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or run it without installing: `uvx --from youtube-kit ytk --help`. Needs Python 3.12 or newer.
|
|
43
|
+
|
|
44
|
+
## Credentials
|
|
45
|
+
|
|
46
|
+
Public data (search, videos, channels, playlists, comments) works with an API key. Anything on your own channel (uploads, edits, deletes, comment moderation, branding, subscriptions, ratings, analytics) needs an OAuth login.
|
|
47
|
+
|
|
48
|
+
1. In the [Google Cloud Console](https://console.cloud.google.com), create a project and enable **YouTube Data API v3**, plus **YouTube Analytics API** for `ytk analytics`.
|
|
49
|
+
2. **API key** for public data: create one and `export YOUTUBE_API_KEY=...`. Without a key, `ytk` uses your OAuth login for public data too.
|
|
50
|
+
3. **OAuth** for your channel:
|
|
51
|
+
1. Configure the OAuth consent screen (user type *External*) and add your Google account as a test user.
|
|
52
|
+
2. Create an OAuth client ID of type *Desktop app*, download its JSON, and save it where `ytk auth status` says `client_secrets_file` lives.
|
|
53
|
+
3. Run `ytk auth login`. It opens a browser and stores a token that the CLI and the MCP server share.
|
|
54
|
+
|
|
55
|
+
> [!NOTE]
|
|
56
|
+
> While the consent screen is in *Testing* status, Google expires the login after 7 days and you need to run `ytk auth login` again. To keep it, set the publishing status to *In production*. Google then shows an "unverified app" warning at login, which is expected for your own client; continue past it.
|
|
57
|
+
|
|
58
|
+
Credentials and `config.toml` live in the user config directory (`~/Library/Application Support/youtube-kit/` on macOS, `~/.config/youtube-kit/` on Linux); `ytk auth status` prints the exact paths. These environment variables override them:
|
|
59
|
+
|
|
60
|
+
| Variable | Purpose |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `YOUTUBE_API_KEY` | API key for public data |
|
|
63
|
+
| `YOUTUBE_CLIENT_SECRETS` | Path to the OAuth client JSON |
|
|
64
|
+
| `YOUTUBE_TOKEN_FILE` | Path to the stored login |
|
|
65
|
+
| `YOUTUBE_CONFIG_FILE` | Path to `config.toml` (delete limits) |
|
|
66
|
+
|
|
67
|
+
## Use it from an agent
|
|
68
|
+
|
|
69
|
+
**Shell agents (Claude Code, Codex and others)** use the CLI through the skill. For Claude Code:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
mkdir -p ~/.claude/skills/youtube
|
|
73
|
+
curl -fsSL https://raw.githubusercontent.com/eukosh/youtube-kit/main/skills/youtube/SKILL.md \
|
|
74
|
+
-o ~/.claude/skills/youtube/SKILL.md
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**MCP clients** run the server with `ytk mcp`. The examples below use `uvx`, which comes with [uv](https://docs.astral.sh/uv/). For Claude Code:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
claude mcp add youtube -- uvx --from youtube-kit ytk mcp
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
For clients configured with JSON (Claude Desktop, Cursor and others):
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"mcpServers": {
|
|
88
|
+
"youtube": {
|
|
89
|
+
"command": "uvx",
|
|
90
|
+
"args": ["--from", "youtube-kit", "ytk", "mcp"],
|
|
91
|
+
"env": { "YOUTUBE_API_KEY": "..." }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The API key is optional; without it the server uses your `ytk auth login` token.
|
|
98
|
+
|
|
99
|
+
## Output and exit codes
|
|
100
|
+
|
|
101
|
+
Every command prints one JSON document on stdout, with null fields left out. On failure stdout stays empty and stderr gets:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{"error": {"type": "not_found", "message": "Video abc123def45 not found."}}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The exit code names the type: 2 bad input, 3 not found, 4 not authorized, 5 quota exceeded, 6 forbidden, 7 network, 8 confirmation required, 9 protected, 10 timeout, 1 anything else. The [skill](https://github.com/eukosh/youtube-kit/blob/main/skills/youtube/SKILL.md#output-contract) says what an agent should do about each.
|
|
108
|
+
|
|
109
|
+
Video, channel and playlist arguments take IDs or pasted URLs; channels also take an `@handle`.
|
|
110
|
+
|
|
111
|
+
## Deleting
|
|
112
|
+
|
|
113
|
+
Agents make mistakes, so deleting videos, playlists and comments is guarded:
|
|
114
|
+
|
|
115
|
+
- **Two steps.** The first call deletes nothing. At a terminal you get a `[y/N]` prompt. An agent gets exit 8 with a description of the target and must run the command again with `--confirm <id>`, so the approval always names the exact thing being deleted.
|
|
116
|
+
- **Damage limit.** A video with more than 100 views, or one that is public and was uploaded more than 7 days ago, can't be deleted here at all; use YouTube Studio. The limits live in `config.toml` (`ytk auth status` shows where):
|
|
117
|
+
|
|
118
|
+
```toml
|
|
119
|
+
[delete_protection]
|
|
120
|
+
max_views = 100
|
|
121
|
+
max_public_age_days = 7
|
|
122
|
+
```
|
|
123
|
+
- **Harness approval.** Have your agent ask you before every delete; the skill has a Claude Code permission snippet for it.
|
|
124
|
+
- **Idempotent.** Deleting something that is already gone succeeds with `"already_gone": true`.
|
|
125
|
+
|
|
126
|
+
This stops mistakes, not a determined agent: anything holding your OAuth token can call the API directly.
|
|
127
|
+
|
|
128
|
+
## Quota
|
|
129
|
+
|
|
130
|
+
Google gives each Cloud project 10,000 units a day, resetting at midnight Pacific time. Reads cost 1 unit per request, `search` 100 per page of 50 results, most writes 50 (deletes a couple more, for the lookup and ownership check), and an upload 1,600. Analytics has its own separate quota.
|
|
131
|
+
|
|
132
|
+
## Contributing
|
|
133
|
+
|
|
134
|
+
Bug reports and pull requests are welcome. See [CONTRIBUTING.md](https://github.com/eukosh/youtube-kit/blob/main/CONTRIBUTING.md) for the development setup, [CHANGELOG.md](https://github.com/eukosh/youtube-kit/blob/main/CHANGELOG.md) for what changed, and [ADR 0001](https://github.com/eukosh/youtube-kit/blob/main/docs/adr/0001-shared-core-cli-and-mcp.md) for how the code fits together. Report security issues privately, as described in [SECURITY.md](https://github.com/eukosh/youtube-kit/blob/main/SECURITY.md).
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
[MIT](https://github.com/eukosh/youtube-kit/blob/main/LICENSE). youtube-kit is not affiliated with or endorsed by Google or YouTube. YouTube is a trademark of Google LLC.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "youtube-kit"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "A CLI (ytk) and MCP server for the YouTube Data and Analytics APIs, built for agents and humans."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
keywords = [
|
|
10
|
+
"youtube",
|
|
11
|
+
"youtube-data-api",
|
|
12
|
+
"youtube-analytics",
|
|
13
|
+
"cli",
|
|
14
|
+
"mcp",
|
|
15
|
+
"model-context-protocol",
|
|
16
|
+
"agents",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 4 - Beta",
|
|
20
|
+
"Environment :: Console",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Programming Language :: Python :: 3.14",
|
|
28
|
+
"Topic :: Multimedia :: Video",
|
|
29
|
+
"Topic :: Utilities",
|
|
30
|
+
"Typing :: Typed",
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
"cyclopts>=4.22,<5",
|
|
34
|
+
"fastmcp>=4.1,<5",
|
|
35
|
+
"google-api-python-client>=2.199.0",
|
|
36
|
+
"google-auth>=2.56",
|
|
37
|
+
"google-auth-oauthlib>=1.4.0",
|
|
38
|
+
"httplib2>=0.22",
|
|
39
|
+
"platformdirs>=4.11",
|
|
40
|
+
"pydantic>=2.13,<3",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[[project.authors]]
|
|
44
|
+
name = "Eugene Kosharnyi"
|
|
45
|
+
email = "eugene.kosharnyi@gmail.com"
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Homepage = "https://github.com/eukosh/youtube-kit"
|
|
49
|
+
Documentation = "https://github.com/eukosh/youtube-kit#readme"
|
|
50
|
+
Issues = "https://github.com/eukosh/youtube-kit/issues"
|
|
51
|
+
Changelog = "https://github.com/eukosh/youtube-kit/blob/main/CHANGELOG.md"
|
|
52
|
+
|
|
53
|
+
[project.scripts]
|
|
54
|
+
ytk = "youtube_kit.cli:main"
|
|
55
|
+
|
|
56
|
+
[build-system]
|
|
57
|
+
requires = ["uv_build>=0.9.5,<0.10"]
|
|
58
|
+
build-backend = "uv_build"
|
|
59
|
+
|
|
60
|
+
[dependency-groups]
|
|
61
|
+
dev = [
|
|
62
|
+
"pytest>=9.1.1",
|
|
63
|
+
"ruff>=0.17.1",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[tool.ruff]
|
|
67
|
+
line-length = 120
|
|
68
|
+
|
|
69
|
+
[tool.ruff.lint]
|
|
70
|
+
extend-select = [
|
|
71
|
+
"I",
|
|
72
|
+
"UP",
|
|
73
|
+
"B",
|
|
74
|
+
"SIM",
|
|
75
|
+
"RUF",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[tool.pytest.ini_options]
|
|
79
|
+
testpaths = ["tests"]
|
|
80
|
+
addopts = [
|
|
81
|
+
"-ra",
|
|
82
|
+
"--strict-markers",
|
|
83
|
+
]
|
|
84
|
+
markers = ["live: hits the real YouTube API (needs LIVE_YOUTUBE_API_KEY)"]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "youtube-kit"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "A CLI (ytk) and MCP server for the YouTube Data and Analytics APIs, built for agents and humans."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
authors = [{ name = "Eugene Kosharnyi", email = "eugene.kosharnyi@gmail.com" }]
|
|
10
|
+
keywords = ["youtube", "youtube-data-api", "youtube-analytics", "cli", "mcp", "model-context-protocol", "agents"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Topic :: Multimedia :: Video",
|
|
22
|
+
"Topic :: Utilities",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"cyclopts>=4.22,<5",
|
|
27
|
+
"fastmcp>=4.1,<5",
|
|
28
|
+
"google-api-python-client>=2.199.0",
|
|
29
|
+
"google-auth>=2.56",
|
|
30
|
+
"google-auth-oauthlib>=1.4.0",
|
|
31
|
+
"httplib2>=0.22",
|
|
32
|
+
"platformdirs>=4.11",
|
|
33
|
+
"pydantic>=2.13,<3",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/eukosh/youtube-kit"
|
|
38
|
+
Documentation = "https://github.com/eukosh/youtube-kit#readme"
|
|
39
|
+
Issues = "https://github.com/eukosh/youtube-kit/issues"
|
|
40
|
+
Changelog = "https://github.com/eukosh/youtube-kit/blob/main/CHANGELOG.md"
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
ytk = "youtube_kit.cli:main"
|
|
44
|
+
|
|
45
|
+
[build-system]
|
|
46
|
+
requires = ["uv_build>=0.9.5,<0.10"]
|
|
47
|
+
build-backend = "uv_build"
|
|
48
|
+
|
|
49
|
+
[dependency-groups]
|
|
50
|
+
dev = [
|
|
51
|
+
"pytest>=9.1.1",
|
|
52
|
+
"ruff>=0.17.1",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[tool.ruff]
|
|
56
|
+
line-length = 120
|
|
57
|
+
|
|
58
|
+
[tool.ruff.lint]
|
|
59
|
+
extend-select = ["I", "UP", "B", "SIM", "RUF"]
|
|
60
|
+
|
|
61
|
+
[tool.pytest.ini_options]
|
|
62
|
+
testpaths = ["tests"]
|
|
63
|
+
addopts = ["-ra", "--strict-markers"]
|
|
64
|
+
markers = ["live: hits the real YouTube API (needs LIVE_YOUTUBE_API_KEY)"]
|
|
File without changes
|