Skip to content
Agentmart
Submit a tool

AGENTS.md · alexta69/metube

AGENTS.md from alexta69/metube: 187 lines covering Project scope — read this before planning a feature, Documentation: where content goes, Tech stack, Build &…

Template by alexta69

IndexedAGPL-3.0★ 15,088
Write a review

Install

Works with Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code. Read the repository before you give any tool access to your data.

curl -fsSL https://raw.githubusercontent.com/alexta69/metube/master/AGENTS.md -o AGENTS.md

Read it and adapt it to your project before use.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

The AGENTS.md file that alexta69/metube (15,087 stars) keeps for coding agents. It has 187 lines in 9 sections: Project scope — read this before planning a feature; Documentation: where content goes; Tech stack; Build & test commands; Commit messages; Project structure; Key conventions; Checklist: adding a per-download option; Security invariants. Use it as a model for your own project's instructions.

Use cases: prompt-engineering, code-generation

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

What's in it

An AGENTS.md file: instructions coding agents (Codex, Cursor, Copilot, Gemini CLI and others) read before working in a repo.

For
Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code
Length
187 lines
File
AGENTS.md

Sections

  1. Project scope — read this before planning a feature
  2. Documentation: where content goes
  3. Tech stack
  4. Build & test commands
  5. Commit messages
  6. Project structure
  7. Key conventions
  8. Checklist: adding a per-download option
  9. Security invariants

First lines (shown under the repo's AGPL-3.0 license)

# Agent Guidelines

## Project scope — read this before planning a feature

MeTube's contract is: give it a URL, it runs yt-dlp well, and correct files appear.
The maintainer holds a deliberate line on what belongs inside that contract, and PRs
on the wrong side of it are declined **regardless of code quality**. Check your plan
against this line before writing any code.

**In scope — improving the write itself:**

- Features that make the file yt-dlp writes at download time come out more correct,
  using only data the extractor already provides (e.g. filling a missing album-artist
  tag from the extractor's own metadata).
- Surfacing functionality yt-dlp itself owns and maintains as first-class UI options
  (e.g. a SponsorBlock toggle that just passes yt-dlp postprocessor params).
- Download queue, subscriptions, output templates, and UI improvements to the
  download workflow.

**Out of scope — managing files after they exist:**

- Tag editors, metadata dialogs, or any workflow that rewrites files after the
  download has finished. This holds even for slimmed-down versions.
- Lookups against external metadata services (iTunes, Deezer, MusicBrainz, etc.).
  More broadly: any new dependency on a third-party API, or new network egress from
  self-hosted instances, beyond what yt-dlp itself performs.
- Library organization: moving/renaming existing files into Artist/Album layouts,
  watch-folder processing, and similar media-manager features. Dedicated tools
  (beets, MusicBrainz Picard, Lidarr) do this properly; the README points users
  to them.

**Corollaries that shape borderline PRs:**

- Site-specific intelligence (parsing playlist-ID prefixes, URL path conventions,
  and other platform internals) is extractor work and belongs upstream in yt-dlp,
  not re-implemented here — it silently breaks when the platform changes and
  MeTube would own the breakage.
- Prefer enriching yt-dlp's info dict and letting its existing pipeline
  (FFmpegMetadata etc.) do the writing, over adding custom per-format tag-writing
  code to MeTube.
- Supplemental processing must never fail a download that otherwise succeeded:
  warn and continue, don't raise.
- Keep feature scope minimal on first submission. A hardcoded sensible default
  beats a configuration surface; follow-ups can add options when users actually
  ask. PRs that bundle several "reasonable next steps" invite rejection of the
  whole.

If a feature idea fails this test, the accepted alternative is usually documentation
on pairing MeTube with the right dedicated tool — a wiki guide, or a pointer in the
README.

## Documentation: where content goes

The README is synced verbatim to Docker Hub, which rejects descriptions over
**25,000 bytes** (CI checks `wc -c README.md`). Rather than trimming prose to fit,
each kind of content has one home:

- **README.md** — what MeTube is, the quick start, and the environment variable
  reference: **one table row per variable**, a sentence or two at most. A variable
  that needs more explanation gets a section in a wiki guide, linked from its row.
  No free-text paragraphs in the configuration section. A PR that adds an env var
  adds its row in the same diff.
- **Wiki** (<https://github.com/alexta69/metube/wiki>, a separate git repository:
  `https://github.com/alexta69/metube.wiki.git`) — guides, concepts, recipes,
  integrations, and troubleshooting. Explanations of behavior go here.
- **CONTRIBUTING.md** — the scope summary for humans, the feature request policy,
  and building and testing locally.

Links in README.md must be absolute URLs: on Docker Hub, relative links break. If the
README passes 15,000 bytes, something in it belongs in the wiki.

## Tech stack

- **Backend:** Python 3.13+, aiohttp, python-socketio 5.x, yt-dlp
- **Frontend:** Angular 22, TypeScript, Bootstrap 5, SASS, ngx-socket-io
- **Package managers:** uv (Python), pnpm (frontend)
- **Container:** Multi-stage Docker (Node builder + Python runtime), multi-arch (amd64/arm64)

## Build & test commands

```bash
# Frontend (run from ui/)
pnpm install --frozen-lockfile
pnpm run lint
pnpm run build
pnpm exec ng test --watch=false

# Backend (run from repo root)
uv sync --frozen --group dev
uv run python -m compileall -q app
uv run pytest app/tests/
```

All of these run in CI (`.github/workflows/main.yml`) on every push to master and must pass.

The backend tests need no frontend build and can run from the repo root or
from `app/`: `app/tests/conftest.py` points `BASE_DIR` at a stand-in UI
directory before `main` is imported.

Every non-markdown push to master builds multi-arch Docker images and cuts a dated
release the same day. **Master is continuously released** — a PR must be
release-ready exactly as merged; there is no stabilization window for follow-up
fixes.

## Commit messages

A commit that resolves an issue must close it, with a GitHub closing keyword in
parentheses at the end of the subject line:

```
fix: stop metadata probes from writing playlist sidecar files (closes #1040)
```

Because master is the default branch and is released on every push, the issue
closes at the moment the fix ships, and keeps a permanent link to the commit that
fixed it. A bare `(#1040)` is only a reference — and reads as a pull-request
number — so it does not count; the keyword is what closes the issue.

Auto-closing leaves only a commit stub on the issue, which is not an answer to
whoever reported it. Post an explanatory comment as well: what the cause was, what
changed, and anything the reporter needs to do differently.

Follow `.editorconfig`:
- Python: 4-space indent
- Everything else (TypeScript, YAML, JSON, HTML): 2-space indent
- UTF-8, LF line endings, trim trailing whitespace, final newline

Frontend additionally uses ESLint (`ui/eslint.config.js`) and Prettier (config in `ui/package.json`: `printWidth=100`, `singleQuote=true`).

## Project structure

```
app/main.py          — HTTP server, Socket.IO events, REST API routes, Config class
app/ytdl.py          — Download queue logic, yt-dlp integration
app/download_options.py — DownloadOptions: one request's options, passed whole through the queue
app/subscriptions.py — Channel/playlist subscription manager
app/state_store.py   — JSON-based persistent storage with atomic writes
app/format_catalog.py — The download options (types, codecs, formats, qualities, labels, defaults)
app/dl_formats.py    — Maps those options onto yt-dlp format selectors and options
app/tests/           — pytest tests (asyncio_mode=auto)
ui/src/app/          — Angular standalone components (no NgModules)
```

## Key conventions

- Backend configuration lives in the `Config` class in `app/main.py` with env-var defaults in `_DEFAULTS`. New env vars go there.
- Download options are defined only in `app/format_catalog.py`. Request validation, `dl_formats`, the UI's form (sent over Socket.IO on connect) and `GET /formats` all read it; never hardcode an option list or id elsewhere. A new codec, format or quality also needs its yt-dlp mapping in `dl_formats`, which `test_format_catalog.py` enforces.
- Real-time communication uses Socket.IO events, not REST polling.
- Frontend uses standalone Angular components with `inject()` for DI, RxJS Subjects for state, and `takeUntilDestroyed()` for cleanup.
- Frontend components use OnPush change detection: subscribe callbacks must call `cdr.markForCheck()`.
- State is persisted as JSON files via `AtomicJsonStore` in `app/state_store.py`.
- Persisted state stays compact: the completed queue deliberately drops bulky entry data (see `_compact_persisted_entry` in `app/ytdl.py`). Don't expand what gets persisted without discussion.
- Custom yt-dlp postprocessors added to `ytdl_params['postprocessors']` run in **list order** within a stage. When combining postprocessors, mirror the ordering the yt-dlp CLI would produce (e.g. sponsor-segment removal before chapter splitting).
- No pre-commit hooks — linting and tests are enforced in CI only.

## Checklist: adding a per-download option

New options on the download form (the `split_by_chapters` pattern) need **all** of
these pieces — the last three are the ones commonly missed:

Signals

Stars
15,088
Forks
1,123
Open issues
7
Last commit (this folder)
Oct 18, 2026 (10 days ago)
Last release
Oct 23, 2026 (6 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
AGPL-3.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026
Cite this page

AGENTS.md · alexta69/metube. Agent Mart. https://agentmart.dev/templates/alexta69-metube-agents-md (last updated 2026-10-24)