{"owner":"Chocobozzz","repo":"PeerTube","hasSkills":true,"totalSkillsCount":73,"totalTokensCount":25681,"categories":["anthropic-skill","root-instruction","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["packages/core-utils/package.json","packages/ffmpeg/tsconfig.json","packages/core-utils/tsconfig.json","client/AGENTS.md","AGENTS.md","packages/ffmpeg/package.json","packages/models/tsconfig.json","packages/models/tsconfig.types.json","packages/node-utils/tsconfig.json","packages/node-utils/package.json","packages/server-commands/package.json","packages/models/package.json","packages/server-commands/tsconfig.json","packages/tests/package.json","packages/tests/tsconfig.json","packages/transcription-devtools/README.md","packages/transcription-devtools/package.json","packages/transcription-devtools/tsconfig.json","packages/transcription/README.md","packages/transcription/package.json","packages/transcription/tsconfig.json","packages/transcription/tsconfig.types.json","packages/types-generator/README.md","packages/types-generator/package.json","packages/types-generator/tsconfig.dist-tmp.json","packages/types-generator/tsconfig.json","packages/types-generator/tsconfig.types.json","packages/typescript-utils/package.json","packages/typescript-utils/tsconfig.json","packages/typescript-utils/tsconfig.types.json","support/doc/plugins/guide.md","packages/tests/fixtures/peertube-plugin-test-broken/package.json","packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json","packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json","packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json","packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json","packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json","packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json","packages/tests/fixtures/peertube-plugin-test-five/package.json","packages/tests/fixtures/peertube-plugin-test-four/package.json","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json","packages/tests/fixtures/peertube-plugin-test-native/package.json","packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json","packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json","packages/tests/fixtures/peertube-plugin-test-secondary/package.json","packages/tests/fixtures/peertube-plugin-test-seven/package.json","packages/tests/fixtures/peertube-plugin-test-six/package.json","packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json","packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json","packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json","packages/tests/fixtures/peertube-plugin-test-transcription/package.json","packages/tests/fixtures/peertube-plugin-test-unloading/package.json","packages/tests/fixtures/peertube-plugin-test-upload-file/package.json","packages/tests/fixtures/peertube-plugin-test-video-constants/package.json","packages/tests/fixtures/peertube-plugin-test-websocket/package.json","packages/tests/fixtures/peertube-plugin-test/package.json","packages/types-generator/src/client/tsconfig.types.json","packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json","packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json","packages/tests/fixtures/ap-json/mastodon/bad-public-key.json","packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json","packages/tests/fixtures/ap-json/mastodon/create.json","packages/tests/fixtures/ap-json/mastodon/http-signature.json","packages/tests/fixtures/ap-json/mastodon/public-key.json","packages/tests/fixtures/ap-json/peertube/announce-without-context.json","packages/tests/fixtures/ap-json/peertube/invalid-keys.json","packages/tests/fixtures/ap-json/peertube/keys.json","packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json","packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json","packages/tests/fixtures/peertube-plugin-test/languages/fr.json","packages/tests/fixtures/transcription/videos/README.md"],"skills":{"packages/core-utils/package.json":"{\n  \"name\": \"@peertube/peertube-core-utils\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","packages/ffmpeg/tsconfig.json":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../models\" },\n    { \"path\": \"../core-utils\" }\n  ]\n}\n","packages/core-utils/tsconfig.json":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../models\" }\n  ]\n}\n","client/AGENTS.md":"# Client — Angular Frontend SPA\n\nPeerTube's web client is an Angular single-page application served\nunder `/client/`. It communicates with the backend exclusively through\nthe REST API (`/api/v1/`). A separate Vite-built embed player lives\nin `src/standalone/` for third-party iframe embedding.\n\n## Directory Structure\n\n- **src/app/** — Main Angular application\n  - `+about/`, `+admin/`, `+home/`, `+login/`, `+signup/`, etc. —\n    Lazy-loaded route modules (prefixed with `+`)\n  - `core/` — Singleton services: auth, routing, plugins, theme,\n    server config, notifications, screen-size helpers\n  - `shared/` — Reusable components & directives organized by domain\n    (`shared-video/`, `shared-forms/`, `shared-moderation/`, etc.)\n  - `header/`, `menu/`, `modal/` — App shell layout components\n  - `helpers/` — Client-side utility functions\n  - `hotkeys/` — Keyboard shortcut definitions\n  - `app.routes.ts` — Top-level route definitions (lazy-loaded)\n  - `app.component.ts` — Root component\n- **src/root-helpers/** — Framework-agnostic helpers (logger, storage,\n  theme manager, translations, plugin manager) shared between the\n  main app and standalone builds\n- **src/standalone/** — Independently built artifacts:\n  - `player/` — PeerTube video player (Vite build, HLS.js + P2P)\n  - `embed-player-api/` — Public npm package for programmatic\n    embed control (`@peertube/embed-api`)\n  - `videos/` — Embed page (`embed.html`) and test harness\n- **src/sass/** — Global SCSS: Bootstrap overrides, PrimeNG theme,\n  utility classes, z-index scale, fonts\n- **src/locale/** — Angular XLIFF translation files\n- **src/assets/** — Static images and assets\n- **src/environments/** — Angular environment configs\n- **e2e/** — End-to-end tests (WebdriverIO + Mocha)\n- **proxy.config.json** — Dev-server proxy to backend (:9000)\n\n## Build & Development Commands\n\nAll commands run from the **repository root** unless noted.\n\n### Development\n\n```bash\n# Full stack: server (:9000) + Angular dev server (:3000)\nnpm run dev\n\n# Client only (requires a running backend on :9000)\nnpm run dev:client\n\n# Embed player only\nnpm run dev:embed\n```\n\nThe Angular dev server proxies `/api`, `/plugins`, `/themes`,\n`/static`, `/lazy-static`, `/socket.io`, and `/client/assets` to the\nbackend at `http://127.0.0.1:9000` (see `proxy.config.json`).\n\n### Build\n\n```bash\n# Full client build (production)\nnpm run build:client\n\n# Embed player build\nnpm run build:embed\n```\n\nOutput goes to `client/dist/` with per-locale sub-directories\n(e.g. `client/dist/en-US/`, `client/dist/fr-FR/`).\n\n### Lint\n\n```bash\n# From repository root\ncd client\n\n# TypeScript + Angular templates (ESLint)\nnpm run lint-ts\n\n# SCSS (Stylelint)\nnpm run lint-scss\n\n# Both\nnpm run lint\n```\n\n### E2E tests\n\n```bash\n# Local browser (from repo root)\nnpm run e2e:local\n\n# BrowserStack\nnpm run e2e:browserstack\n```\n\nE2E uses **WebdriverIO** with a **Mocha** framework. Config files are\nin `e2e/` (`wdio.local.conf.ts`, `wdio.browserstack.conf.ts`).\n\n## Code Style & Conventions\n\n### TypeScript / ESLint\n\nThe client has its own `eslint.config.mjs` extending\n`eslint-config-love` and `angular-eslint`. Key rules match the\nserver:\n\n| Rule                | Value                             |\n|---------------------|-----------------------------------|\n| Semicolons          | **never** (`@stylistic/semi`)     |\n| Max line length     | 140 characters                    |\n| Array brackets      | Spaces inside `[ 'a', 'b' ]`     |\n| Trailing newline    | Required (`eol-last`)             |\n| Indentation         | 2 spaces                          |\n\n### Angular-specific rules\n\n| Rule                                     | Value                    |\n|------------------------------------------|--------------------------|\n| Component selector prefix               | `my-` (kebab-case)       |\n| Directive selector prefix               | `my` (camelCase)         |\n| View encapsulation                       | Required (enforced)      |\n\n### SCSS / Stylelint\n\nConfigured in `.stylelintrc.json`, extends\n`stylelint-config-sass-guidelines` with `stylelint-order`. Key rules:\n\n- Declaration order: custom properties → declarations → `@include`\n- Max nesting depth: 8\n- Max compound selectors: 9\n- `::ng-deep` pseudo-element allowed\n\n### Naming patterns\n\n- Lazy-loaded route folders: `+feature-name/` (e.g. `+admin/`,\n  `+video-watch/`)\n- Shared modules: `shared-domain/` (e.g. `shared-video/`,\n  `shared-forms/`)\n- Services: PascalCase with `Service` suffix\n  (`AuthService`, `ServerService`)\n- Components: PascalCase with `Component` suffix, selector prefixed\n  `my-` (`my-video-miniature`)\n- Path aliases: `@app/*` → `src/app/*`,\n  `@root-helpers/*` → `src/root-helpers/*`\n\n### Internationalization\n\n- Source locale: `en` (base href `/client/en-US/`)\n- Translation files: XLIFF format in `src/locale/`\n- Merge tool: `@peertube/xliffmerge` (config: `.xliffmerge.json`)\n- Use Angular `$localize` / `i18n` attributes; do NOT use raw strings\n  for user-visible text\n\n## Architecture Notes\n\n```\n┌────────────────────────────────────────────────────────┐\n│                 Angular SPA (client/)                   │\n│                                                         │\n│  ┌──────────┐  ┌──────────────┐  ┌──────────────────┐  │\n│  │  Routes   │  │  Core        │  │  Shared          │  │\n│  │ (+about,  │  │ (auth, REST, │  │ (forms, video    │  │\n│  │  +admin,  │──│  plugins,    │──│  miniature,      │  │\n│  │  +videos) │  │  server,     │  │  moderation...)  │  │\n│  │           │  │  theme)      │  │                  │  │\n│  └──────────┘  └──────┬───────┘  └──────────────────┘  │\n│                        │                                │\n│  ┌─────────────────────▼────────────────────────────┐   │\n│  │           root-helpers (no Angular dep)           │   │\n│  │  logger, storage, plugins-manager, theme, i18n   │   │\n│  └──────────────────────────────────────────────────┘   │\n│                                                         │\n│  ┌─────────────────────────────────────────────────┐    │\n│  │         standalone/ (Vite builds)               │    │\n│  │  player/ │ embed-player-api/ │ videos/embed     │    │\n│  └─────────────────────────────────────────────────┘    │\n└────────────────────────┬────────────────────────────────┘\n                         │ HTTP (REST API)\n                         ▼\n              ┌──────────────────────┐\n              │  Express Backend     │\n              │  (:9000 /api/v1/*)   │\n              └──────────────────────┘\n```\n\n- **Lazy loading**: Each `+feature/` folder exports route configs\n  loaded via `loadChildren` in `app.routes.ts`\n- **Core services**: Singletons bootstrapped in `main.ts` via\n  `getCoreProviders()` — auth, REST client, server config polling,\n  plugin hooks, theme manager\n- **Plugin hooks**: Client-side plugins register via\n  `HooksService` / `PluginService` in `core/plugins/`\n- **State management**: No dedicated store library; services hold\n  state, components subscribe via RxJS observables\n- **UI framework**: Bootstrap 5 + PrimeNG + ng-bootstrap;\n  global SCSS in `src/sass/`\n- **Video player**: Custom build in `standalone/player/` using\n  Video.js + HLS.js + P2P Media Loader; embedded via\n  `standalone/videos/embed.html`\n\n## Agent Guardrails\n\n### Files agents must NOT modify\n\n- `src/locale/*.xlf` — Generated translation files; updated via\n  `npm run i18n:update` only\n- `dist/` — Build output; never edit manually\n- `node_modules/` — Managed by pnpm\n- `.angular/` — Angular build cache\n\n### Required checks before pushing\n\n1. `cd client && npm run lint` must pass (TS + SCSS)\n2. Production build must succeed: `npm run build:client`\n   (from repo root)\n3. If new user-visible strings added: extract with\n   `npm run i18n:create-custom-files` and verify XLIFF\n\n### Boundaries\n\n- Do not import from `server/` — the client communicates with the\n  backend exclusively via the REST API\n- Do not import Angular-specific code in `root-helpers/` or\n  `standalone/` — these must remain framework-agnostic\n- Shared API types come from `@peertube/peertube-models` and\n  `@peertube/peertube-core-utils` (workspace packages)\n- Do not add new npm dependencies without explicit approval\n\n## Further Reading\n\n- [../support/doc/plugins/guide.md](../support/doc/plugins/guide.md)\n  — Plugin & theme development (client hooks)\n- [src/standalone/embed-player-api/README.md](src/standalone/embed-player-api/README.md)\n  — Embed player API documentation\n- [../support/doc/api/embeds.md](../support/doc/api/embeds.md)\n  — Embed integration guide\n- [../AGENTS.md](../AGENTS.md)\n  — Root project AGENTS.md (server, build, CI, testing)\n","AGENTS.md":"# Project Overview\n\nPeerTube is an open-source, ActivityPub-federated video streaming platform\nthat uses P2P technology directly in web browsers. Developed by Framasoft\nunder the AGPL-3.0 license, it provides a decentralized alternative to\ncentralized video platforms. The server is a Node.js/Express API with a\nSequelize ORM (PostgreSQL), background job processing (BullMQ/Redis),\nActivityPub federation, and an Angular SPA client. Video transcoding is\nhandled via FFmpeg, with optional distributed runners.\n\n## Repository Structure\n\n- **apps/** — Standalone CLI applications (`peertube-cli`, `peertube-runner`)\n- **client/** — Angular frontend SPA (separate build system)\n- **config/** — YAML configuration files for dev, test, and production\n- **packages/** — Shared workspace packages (monorepo):\n  - `core-utils/` — Shared pure-JS utilities\n  - `ffmpeg/` — FFmpeg wrapper library\n  - `models/` — Shared TypeScript interfaces and API types\n  - `node-utils/` — Node.js-specific helpers\n  - `server-commands/` — HTTP client helpers used by tests\n  - `tests/` — Full test suite (API, CLI, plugins, feeds, etc.)\n  - `transcription/` — Speech-to-text engine integration\n  - `transcription-devtools/` — Transcription benchmarking tools\n  - `types-generator/` — Generates the public `@peertube/peertube-types`\n    package\n  - `typescript-utils/` — Generic TypeScript helpers\n- **scripts/** — Build, CI, dev, release, and i18n shell scripts\n- **server/** — Backend entry point and core application code\n  - `server.ts` — Process entry point\n  - `core/controllers/` — Express route handlers (API, ActivityPub,\n    feeds, tracker)\n  - `core/models/` — Sequelize database models (14 categories)\n  - `core/lib/` — Business logic (transcoding, live, job queue,\n    ActivityPub, plugins, runners, notifications, etc.)\n  - `core/middlewares/` — Auth, rate-limiting, validation, caching, CSP\n  - `core/helpers/` — Utility functions and custom validators\n  - `core/initializers/` — App bootstrap, constants, DB migrations,\n    config loading\n  - `core/types/` — Internal TypeScript type augmentations\n- **support/** — Documentation, Docker, Nginx configs, OpenAPI spec\n\n## Build & Development Commands\n\n### Prerequisites\n\n- Node.js >= 22.x\n- pnpm >= 12 (do **not** use npm or yarn for install)\n- PostgreSQL >= 14 with `pg_trgm` and `unaccent` extensions\n- Redis >= 6.x\n- FFmpeg >= 4.3\n- Python >= 3.8 (for some test tooling)\n\n### Install dependencies\n\n```bash\npnpm install --frozen-lockfile\n```\n\n### Build\n\n```bash\n# Build server only (backend work)\nnpm run build:server\n\n# Build full application (server + client)\nnpm run build\n\n# Build tests\nnpm run build:tests\n\n# Build individual apps\nnpm run build:peertube-cli\nnpm run build:peertube-runner\n```\n\n### Development\n\n```bash\n# Server-only with hot reload (recommended for backend work)\nnpm run dev:server        # http://localhost:9000\n\n# Full stack (server + Angular client)\nnpm run dev               # server :9000, client :3000\n\n# Dev credentials: root / test\n```\n\n### Lint & type-check\n\n```bash\n# Full lint (oxlint + OpenAPI validation)\nnpm run lint\n\n# Oxlint only\nnpm run oxlint\n\n# Validate OpenAPI spec\nnpm run swagger-cli -- validate support/doc/api/openapi.yaml\n\n# TypeScript compilation check\nnpm run tsc -b server/tsconfig.json\n```\n\n### Run in production\n\n```bash\nnpm run start              # server + client\nnpm run start:server       # server only (--no-client)\n```\n\n## Code Style & Conventions\n\n### Formatting (enforced by Oxlint)\n\n| Rule                | Value                                 |\n|---------------------|---------------------------------------|\n| Semicolons          | **never** (`@stylistic/semi`)         |\n| Max line length     | 140 characters                        |\n| Quotes              | Single quotes (TypeScript default)    |\n| Array brackets      | Spaces inside `[ 'a', 'b' ]`         |\n| Trailing newline    | Required (`eol-last`)                 |\n| Indentation         | 2 spaces (TypeScript convention)      |\n\n### Naming patterns\n\n- Database models: `VideoModel`, `UserModel` — PascalCase + `Model` suffix\n- Internal type aliases: `MVideo`, `MVideoWithChannel` — `M` prefix for\n  Sequelize model types with specific association requirements\n- Controllers: one file per resource, registered in parent `index.ts`\n- Validators: mirror controller structure under\n  `server/core/middlewares/validators/`\n\n### Controller pattern\n\n```typescript\nimport express from 'express'\nimport { apiRateLimiter, asyncMiddleware } from '../../middlewares/index.js'\n\nconst router = express.Router()\nrouter.use(apiRateLimiter)  // always include rate limiting\n\nrouter.get('/:id',\n  validationMiddleware,     // always validate inputs\n  asyncMiddleware(handler)  // always wrap async handlers\n)\n```\n\nSecondary processes (`--role=secondary`) serve every route. A route that needs a state only the primary\nprocess has (its file system, data kept in its memory, live sessions, the tracker...) must start with the\n`primaryOnly` middleware, before any side effect: a secondary answers `421` and nginx replays the request on\nthe primary. Requests whose body nginx streams (`proxy_request_buffering off` locations) cannot be replayed:\nroute them to `backend` in the `$peertube_pool` map of `support/nginx/peertube`.\n\n### Commit messages\n\nNo formal commit-message template.\n\n### Oxlint config\n\nDefined in `oxlint.config.mjs`. Applies to `server/**/*.ts`,\n`scripts/**/*.ts`, `packages/**/*.ts`, `apps/**/*.ts`. The `client/`\ndirectory has its own lint config.\n\n## Architecture Notes\n\n```\n                  ┌──────────────────────────────────────────┐\n                  │            Reverse Proxy (Nginx)         │\n                  └──────────────┬───────────────────────────┘\n                                 │\n              ┌──────────────────▼──────────────────────┐\n              │          Express.js API Server           │\n              │  (server/server.ts → core/controllers/)  │\n              │                                          │\n              │  ┌─────────┐ ┌──────────┐ ┌──────────┐  │\n              │  │  REST   │ │Activity- │ │  Feeds/  │  │\n              │  │  API    │ │  Pub     │ │  oEmbed  │  │\n              │  │  /api/* │ │  /inbox  │ │  /feeds  │  │\n              │  └────┬────┘ └────┬─────┘ └────┬─────┘  │\n              │       │           │             │        │\n              │  ┌────▼───────────▼─────────────▼────┐  │\n              │  │       Middleware Pipeline          │  │\n              │  │  (auth, validators, rate-limit)    │  │\n              │  └────────────────┬───────────────────┘  │\n              │                   │                      │\n              │  ┌────────────────▼───────────────────┐  │\n              │  │        Business Logic (lib/)       │  │\n              │  │  videos, live, transcoding,        │  │\n              │  │  federation, notifications,        │  │\n              │  │  plugins, runners                  │  │\n              │  └──┬──────────┬──────────────┬───┘   │\n              └─────┼──────────┼──────────────┼───────┘\n                    │          │              │\n          ┌────────▼──┐ ┌─────▼─────┐ ┌──────▼──────┐\n          │PostgreSQL │ │   Redis   │ │  FFmpeg /   │\n          │(Sequelize)│ │ (BullMQ   │ │  Runners    │\n          │           │ │  + cache) │ │             │\n          └───────────┘ └───────────┘ └─────────────┘\n```\n\n**Startup sequence** (`server/server.ts`):\n\n1. Register OpenTelemetry tracing\n2. Pre-init checks (config, FFmpeg, Node.js version)\n3. Connect to PostgreSQL, run migrations\n4. Initialize Sequelize models and load i18n\n5. Configure Express middleware stack (proxy trust, CSP, CORS,\n   rate-limiting, OAuth2 auth, express-validator)\n6. Mount route controllers and start listening\n\n**Key data flows**:\n\n- **Video upload**: REST API → validator middleware → `lib/video.ts` →\n  job queue → FFmpeg transcoding → HLS/web-video files → object\n  storage or local filesystem\n- **Federation**: Incoming ActivityPub requests → signature\n  verification → `lib/activitypub/` processors → local DB updates +\n  outgoing fan-out\n- **Live streaming**: RTMP ingest → FFmpeg segmenter → HLS manifest →\n  P2P delivery via WebSocket tracker\n\n## Testing Strategy\n\n### Test framework\n\n- **Mocha** for all server/API tests\n- **GNU Parallel** for running test files concurrently in CI\n- Tests live in `packages/tests/src/` (TypeScript source) and are\n  compiled to `packages/tests/dist/`\n\n### Preparation\n\n```bash\n# Create PostgreSQL superuser for test DB management\nsudo -u postgres createuser $(whoami) --createdb --superuser\n\n# Clean test databases\nnpm run clean:server:test\n\n# Build server + tests\nnpm run build:server\nnpm run build:tests\n```\n\n### Running tests\n\n```bash\n# Full suite (slow, ~45-60 min)\nnpm run test\n\n# Run a specific CI suite\nnpm run ci -- api-check-params-search       # check-params, search\nnpm run ci -- api-videos-1 | api-videos-2   # videos, split in 2 shards balanced by duration\nnpm run ci -- api-server                    # server\nnpm run ci -- api-live-scalability          # live, horizontal-scalability\nnpm run ci -- api-users-stats               # users, stats\nnpm run ci -- api-moderation-notifications  # moderation, notifications\nnpm run ci -- api-federation                # activitypub, redundancy\nnpm run ci -- api-object-storage            # object-storage\nnpm run ci -- api-transcoding-1 | api-transcoding-2  # transcoding + runners, split in 2 shards\nnpm run ci -- client      # feeds, client, misc-endpoints, plugins\nnpm run ci -- cli-plugin  # CLI and plugin tests\nnpm run ci -- lint        # OXlint + OpenAPI validation + client lint\nnpm run ci -- transcription\nnpm run ci -- external-plugins\n\n# Run a single test file\nnpm run mocha -- --timeout 30000 --exit --bail \\\n  packages/tests/src/api/videos/single-server.ts\n```\n\n### External test dependencies (Docker)\n\nSome tests require these containers:\n\n```bash\ndocker run -p 9444:8000 -e S3BACKEND=mem -e REMOTE_MANAGEMENT_DISABLE=1 \\\n  -e SCALITY_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \\\n  -e SCALITY_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \\\n  ghcr.io/scality/cloudserver:9.3.20\ndocker run -p 10389:10389 chocobozzz/docker-test-openldap\ndocker run -p 8082:8080 \\\n  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \\\n  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \\\n  chocobozzz/peertube-tests-keycloak\n```\n\n### CI pipeline\n\nGitHub Actions (`.github/workflows/test.yml`), Ubuntu 22.04, Node.js\n22.x. Matrix strategy runs suites in parallel: `types-package`,\n`client`, the `api-*` suites listed above, `cli-plugin`, `lint`, `transcription`,\n`external-plugins`.\n\nServices provisioned per job: PostgreSQL 10, Redis, LDAP, S3 Ninja,\nKeycloak.\n\n### Environment variables for tests\n\n| Variable                                   | Purpose                     |\n|--------------------------------------------|-----------------------------|\n| `DISABLE_HTTP_IMPORT_TESTS=true`           | Skip flaky HTTP import tests|\n| `DISABLE_HTTP_YOUTUBE_IMPORT_TESTS=true`   | Skip YouTube import tests   |\n| `ENABLE_OBJECT_STORAGE_TESTS=true`         | Enable S3 tests             |\n\n## Security & Compliance\n\n- **License**: AGPL-3.0 — all network-facing modifications must be\n  published under the same license.\n- **Secrets**: The `secrets.peertube` key in `config/*.yaml` must be\n  generated via `openssl rand -hex 32`. Never commit secrets; use\n  `config/local-*.json` overrides (gitignored) or environment variables.\n- **OAuth2**: Access tokens expire in 1 day; refresh tokens in 2 weeks\n  (configurable in `config/default.yaml`).\n- **Rate limiting**: All API endpoints are rate-limited by default\n  (`apiRateLimiter` middleware). Specific limits per category (login,\n  signup, ActivityPub, etc.) are configured in `config/default.yaml`.\n- **CSP**: Content-Security-Policy headers are configurable and applied\n  via `server/core/middlewares/csp.ts`.\n- **Input validation**: Every controller uses express-validator\n  middleware defined in `server/core/middlewares/validators/`.\n- **Vulnerability reporting**: `peertube-security@framasoft.org` —\n  see `SECURITY.md`.\n- **Dependency scanning**: No automated scanner configuration found in\n  the repo.\n\n## Agent Guardrails\n\n### Files and directories agents must NOT modify\n\n- `config/local-*.json` — User-local config overrides (gitignored)\n- `config/production.yaml.example` — Template; changes need release\n  coordination\n- `server/core/initializers/migrations/` — Existing migration files are\n  immutable once released; only append new ones\n- `pnpm-lock.yaml` — Regenerated by `pnpm install`; never edit manually\n- `support/doc/api/openapi.yaml` — Must stay in sync with controllers;\n  validate with `npm run swagger-cli -- validate`\n\n### Required checks before pushing\n\n1. `npm run build:server` must succeed\n2. `npm run lint` must pass\n3. If API surface changed: `npm run swagger-cli -- validate\n   support/doc/api/openapi.yaml`\n4. If database schema changed: create a new migration file **and**\n   increment `LAST_MIGRATION_VERSION` in\n   `server/core/initializers/constants.ts`\n\n### Boundaries\n\n- Do not run `pnpm install` without `--frozen-lockfile`\n- Do not use `npm install` or `yarn` — this project uses **pnpm**\n- Do not add dependencies without explicit approval\n- Do not modify test Docker images or CI service definitions without\n  review\n- Maximum concurrency for background jobs is configured in constants;\n  do not change without benchmarking\n\n## Extensibility Hooks\n\n### Plugin system\n\nPeerTube supports server and client plugins via a hook-based\narchitecture. Plugins register `filter`, `action`, and `static`\nhooks—see `support/doc/plugins/guide.md`.\n\n- Plugin names follow `peertube-plugin-*` (themes: `peertube-theme-*`)\n- Server hooks are registered in `server/core/lib/plugins/`\n- Plugin management API: `/api/v1/plugins`\n- Install/uninstall scripts: `npm run plugin:install`,\n  `npm run plugin:uninstall`\n\n### Configuration\n\nAll runtime configuration is in YAML under `config/`. Local overrides\nuse `config/local-*.json` files (gitignored). Key env vars:\n\n| Variable              | Purpose                              |\n|-----------------------|--------------------------------------|\n| `NODE_ENV`            | `production`, `development`, `test`  |\n| `NODE_CONFIG_DIR`     | Override config directory             |\n| `LOGGER_LEVEL`        | `debug`, `info`, `warn`, `error`     |\n| `PT_INITIAL_ROOT_PASSWORD` | Set root password on first run  |\n\n### Runners (distributed transcoding)\n\nExternal `peertube-runner` processes poll the API for transcoding jobs.\nConfigured in `server/core/lib/runners/` and managed through the\n`/api/v1/runners` endpoints.\n\n### OpenTelemetry\n\nTracing and metrics are instrumented via `@opentelemetry/*` packages.\nExport to an OTLP endpoint like Jaeger (tracing) or Prometheus (metrics) is configurable in\n`config/default.yaml` under the `open_telemetry` key.\n\n## Further Reading\n\n- [support/doc/development/server.md](support/doc/development/server.md)\n  — Server code conventions and new-feature walkthrough\n- [Horizontal scalability](https://docs.joinpeertube.org/maintain/horizontal-scalability)\n  — Running several processes (`--role=secondary`) for one instance\n- [support/doc/development/tests.md](support/doc/development/tests.md)\n  — Test setup and execution guide\n- [support/doc/plugins/guide.md](support/doc/plugins/guide.md)\n  — Plugin & theme development guide\n- [support/doc/api/openapi.yaml](support/doc/api/openapi.yaml)\n  — OpenAPI 3.0 specification\n- [support/doc/production.md](support/doc/production.md)\n  — Production deployment guide\n- [support/doc/docker.md](support/doc/docker.md)\n  — Docker deployment guide\n- [support/doc/development/lib.md](support/doc/development/lib.md)\n  — Library / business-logic documentation\n- [SECURITY.md](SECURITY.md) — Vulnerability disclosure policy\n- [FAQ.md](FAQ.md) — Frequently asked questions\n","packages/ffmpeg/package.json":"{\n  \"name\": \"@peertube/peertube-ffmpeg\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","packages/models/tsconfig.json":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  }\n}\n","packages/models/tsconfig.types.json":"{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../types-generator/dist-tmp/peertube-models\",\n    \"tsBuildInfoFile\": \"../types-generator/dist-tmp/peertube-models/.tsbuildinfo\",\n    \"stripInternal\": true,\n    \"removeComments\": false,\n    \"emitDeclarationOnly\": true\n  }\n}\n","packages/node-utils/tsconfig.json":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../core-utils\" }\n  ]\n}\n","packages/node-utils/package.json":"{\n  \"name\": \"@peertube/peertube-node-utils\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","packages/server-commands/package.json":"{\n  \"name\": \"@peertube/peertube-server-commands\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {\n    \"@aws-sdk/client-s3\": \"^3.1161.0\",\n    \"@types/superagent\": \"^8.1.11\",\n    \"@types/supertest\": \"^7.2.1\",\n    \"supertest\": \"^7.3.1\"\n  },\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {\n    \"@peertube/peertube-core-utils\": \"workspace:*\",\n    \"@peertube/peertube-models\": \"workspace:*\",\n    \"@peertube/peertube-node-utils\": \"workspace:*\",\n    \"@peertube/peertube-typescript-utils\": \"workspace:*\"\n  }\n}\n","packages/models/package.json":"{\n  \"name\": \"@peertube/peertube-models\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"type\": \"module\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","packages/server-commands/tsconfig.json":"# Server-commands Skill\n\nPath: `packages/server-commands/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/server-commands/tsconfig.json)","packages/tests/package.json":"# Tests Skill\n\nPath: `packages/tests/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/package.json)","packages/tests/tsconfig.json":"# Tests Skill\n\nPath: `packages/tests/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/tsconfig.json)","packages/transcription-devtools/README.md":"# transcription-devtools Documentation\n\nPath: `packages/transcription-devtools/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/README.md)","packages/transcription-devtools/package.json":"# Transcription-devtools Skill\n\nPath: `packages/transcription-devtools/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/package.json)","packages/transcription-devtools/tsconfig.json":"# Transcription-devtools Skill\n\nPath: `packages/transcription-devtools/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/tsconfig.json)","packages/transcription/README.md":"# transcription Documentation\n\nPath: `packages/transcription/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/README.md)","packages/transcription/package.json":"# Transcription Skill\n\nPath: `packages/transcription/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/package.json)","packages/transcription/tsconfig.json":"# Transcription Skill\n\nPath: `packages/transcription/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/tsconfig.json)","packages/transcription/tsconfig.types.json":"# Transcription Skill\n\nPath: `packages/transcription/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/tsconfig.types.json)","packages/types-generator/README.md":"# types-generator Documentation\n\nPath: `packages/types-generator/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/README.md)","packages/types-generator/package.json":"# Types-generator Skill\n\nPath: `packages/types-generator/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/package.json)","packages/types-generator/tsconfig.dist-tmp.json":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.dist-tmp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.dist-tmp.json)","packages/types-generator/tsconfig.json":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.json)","packages/types-generator/tsconfig.types.json":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.types.json)","packages/typescript-utils/package.json":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/package.json)","packages/typescript-utils/tsconfig.json":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/tsconfig.json)","packages/typescript-utils/tsconfig.types.json":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/tsconfig.types.json)","support/doc/plugins/guide.md":"# Plugins Skill\n\nPath: `support/doc/plugins/guide.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/support/doc/plugins/guide.md)","packages/tests/fixtures/peertube-plugin-test-broken/package.json":"# Peertube-plugin-test-broken Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-broken/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-broken/package.json)","packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json":"# Peertube-plugin-test-css-sourcemap Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json)","packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json":"# Peertube-plugin-test-external-auth-four Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json)","packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json":"# Peertube-plugin-test-external-auth-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json)","packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json":"# Peertube-plugin-test-external-auth-three Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json)","packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json":"# Peertube-plugin-test-external-auth-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json)","packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json":"# Peertube-plugin-test-filter-translations Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json)","packages/tests/fixtures/peertube-plugin-test-five/package.json":"# Peertube-plugin-test-five Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-five/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-five/package.json)","packages/tests/fixtures/peertube-plugin-test-four/package.json":"# Peertube-plugin-test-four Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-four/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-four/package.json)","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json":"# Peertube-plugin-test-id-pass-auth-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json)","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json":"# Peertube-plugin-test-id-pass-auth-three Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json)","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json":"# Peertube-plugin-test-id-pass-auth-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json)","packages/tests/fixtures/peertube-plugin-test-native/package.json":"# Peertube-plugin-test-native Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-native/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-native/package.json)","packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json":"# Peertube-plugin-test-podcast-custom-tags Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json)","packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json":"# Peertube-plugin-test-secondary-failure Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json)","packages/tests/fixtures/peertube-plugin-test-secondary/package.json":"# Peertube-plugin-test-secondary Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-secondary/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-secondary/package.json)","packages/tests/fixtures/peertube-plugin-test-seven/package.json":"# Peertube-plugin-test-seven Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-seven/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-seven/package.json)","packages/tests/fixtures/peertube-plugin-test-six/package.json":"# Peertube-plugin-test-six Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-six/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-six/package.json)","packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json":"# Peertube-plugin-test-slow-live-setup Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json)","packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json":"# Peertube-plugin-test-transcoding-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json)","packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json":"# Peertube-plugin-test-transcoding-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json)","packages/tests/fixtures/peertube-plugin-test-transcription/package.json":"# Peertube-plugin-test-transcription Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcription/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcription/package.json)","packages/tests/fixtures/peertube-plugin-test-unloading/package.json":"# Peertube-plugin-test-unloading Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-unloading/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-unloading/package.json)","packages/tests/fixtures/peertube-plugin-test-upload-file/package.json":"# Peertube-plugin-test-upload-file Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-upload-file/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-upload-file/package.json)","packages/tests/fixtures/peertube-plugin-test-video-constants/package.json":"# Peertube-plugin-test-video-constants Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-video-constants/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-video-constants/package.json)","packages/tests/fixtures/peertube-plugin-test-websocket/package.json":"# Peertube-plugin-test-websocket Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-websocket/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-websocket/package.json)","packages/tests/fixtures/peertube-plugin-test/package.json":"# Peertube-plugin-test Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test/package.json)","packages/types-generator/src/client/tsconfig.types.json":"# Client Skill\n\nPath: `packages/types-generator/src/client/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/src/client/tsconfig.types.json)","packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json)","packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json)","packages/tests/fixtures/ap-json/mastodon/bad-public-key.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-public-key.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-public-key.json)","packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json)","packages/tests/fixtures/ap-json/mastodon/create.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/create.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create.json)","packages/tests/fixtures/ap-json/mastodon/http-signature.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/http-signature.json)","packages/tests/fixtures/ap-json/mastodon/public-key.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/public-key.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/public-key.json)","packages/tests/fixtures/ap-json/peertube/announce-without-context.json":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/announce-without-context.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/announce-without-context.json)","packages/tests/fixtures/ap-json/peertube/invalid-keys.json":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/invalid-keys.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/invalid-keys.json)","packages/tests/fixtures/ap-json/peertube/keys.json":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/keys.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/keys.json)","packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json)","packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json)","packages/tests/fixtures/peertube-plugin-test/languages/fr.json":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test/languages/fr.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test/languages/fr.json)","packages/tests/fixtures/transcription/videos/README.md":"# videos Documentation\n\nPath: `packages/tests/fixtures/transcription/videos/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/transcription/videos/README.md)"},"files":{"packages/core-utils/package.json":"{\n  \"name\": \"@peertube/peertube-core-utils\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","packages/ffmpeg/tsconfig.json":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../models\" },\n    { \"path\": \"../core-utils\" }\n  ]\n}\n","packages/core-utils/tsconfig.json":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../models\" }\n  ]\n}\n","client/AGENTS.md":"# Client — Angular Frontend SPA\n\nPeerTube's web client is an Angular single-page application served\nunder `/client/`. It communicates with the backend exclusively through\nthe REST API (`/api/v1/`). A separate Vite-built embed player lives\nin `src/standalone/` for third-party iframe embedding.\n\n## Directory Structure\n\n- **src/app/** — Main Angular application\n  - `+about/`, `+admin/`, `+home/`, `+login/`, `+signup/`, etc. —\n    Lazy-loaded route modules (prefixed with `+`)\n  - `core/` — Singleton services: auth, routing, plugins, theme,\n    server config, notifications, screen-size helpers\n  - `shared/` — Reusable components & directives organized by domain\n    (`shared-video/`, `shared-forms/`, `shared-moderation/`, etc.)\n  - `header/`, `menu/`, `modal/` — App shell layout components\n  - `helpers/` — Client-side utility functions\n  - `hotkeys/` — Keyboard shortcut definitions\n  - `app.routes.ts` — Top-level route definitions (lazy-loaded)\n  - `app.component.ts` — Root component\n- **src/root-helpers/** — Framework-agnostic helpers (logger, storage,\n  theme manager, translations, plugin manager) shared between the\n  main app and standalone builds\n- **src/standalone/** — Independently built artifacts:\n  - `player/` — PeerTube video player (Vite build, HLS.js + P2P)\n  - `embed-player-api/` — Public npm package for programmatic\n    embed control (`@peertube/embed-api`)\n  - `videos/` — Embed page (`embed.html`) and test harness\n- **src/sass/** — Global SCSS: Bootstrap overrides, PrimeNG theme,\n  utility classes, z-index scale, fonts\n- **src/locale/** — Angular XLIFF translation files\n- **src/assets/** — Static images and assets\n- **src/environments/** — Angular environment configs\n- **e2e/** — End-to-end tests (WebdriverIO + Mocha)\n- **proxy.config.json** — Dev-server proxy to backend (:9000)\n\n## Build & Development Commands\n\nAll commands run from the **repository root** unless noted.\n\n### Development\n\n```bash\n# Full stack: server (:9000) + Angular dev server (:3000)\nnpm run dev\n\n# Client only (requires a running backend on :9000)\nnpm run dev:client\n\n# Embed player only\nnpm run dev:embed\n```\n\nThe Angular dev server proxies `/api`, `/plugins`, `/themes`,\n`/static`, `/lazy-static`, `/socket.io`, and `/client/assets` to the\nbackend at `http://127.0.0.1:9000` (see `proxy.config.json`).\n\n### Build\n\n```bash\n# Full client build (production)\nnpm run build:client\n\n# Embed player build\nnpm run build:embed\n```\n\nOutput goes to `client/dist/` with per-locale sub-directories\n(e.g. `client/dist/en-US/`, `client/dist/fr-FR/`).\n\n### Lint\n\n```bash\n# From repository root\ncd client\n\n# TypeScript + Angular templates (ESLint)\nnpm run lint-ts\n\n# SCSS (Stylelint)\nnpm run lint-scss\n\n# Both\nnpm run lint\n```\n\n### E2E tests\n\n```bash\n# Local browser (from repo root)\nnpm run e2e:local\n\n# BrowserStack\nnpm run e2e:browserstack\n```\n\nE2E uses **WebdriverIO** with a **Mocha** framework. Config files are\nin `e2e/` (`wdio.local.conf.ts`, `wdio.browserstack.conf.ts`).\n\n## Code Style & Conventions\n\n### TypeScript / ESLint\n\nThe client has its own `eslint.config.mjs` extending\n`eslint-config-love` and `angular-eslint`. Key rules match the\nserver:\n\n| Rule                | Value                             |\n|---------------------|-----------------------------------|\n| Semicolons          | **never** (`@stylistic/semi`)     |\n| Max line length     | 140 characters                    |\n| Array brackets      | Spaces inside `[ 'a', 'b' ]`     |\n| Trailing newline    | Required (`eol-last`)             |\n| Indentation         | 2 spaces                          |\n\n### Angular-specific rules\n\n| Rule                                     | Value                    |\n|------------------------------------------|--------------------------|\n| Component selector prefix               | `my-` (kebab-case)       |\n| Directive selector prefix               | `my` (camelCase)         |\n| View encapsulation                       | Required (enforced)      |\n\n### SCSS / Stylelint\n\nConfigured in `.stylelintrc.json`, extends\n`stylelint-config-sass-guidelines` with `stylelint-order`. Key rules:\n\n- Declaration order: custom properties → declarations → `@include`\n- Max nesting depth: 8\n- Max compound selectors: 9\n- `::ng-deep` pseudo-element allowed\n\n### Naming patterns\n\n- Lazy-loaded route folders: `+feature-name/` (e.g. `+admin/`,\n  `+video-watch/`)\n- Shared modules: `shared-domain/` (e.g. `shared-video/`,\n  `shared-forms/`)\n- Services: PascalCase with `Service` suffix\n  (`AuthService`, `ServerService`)\n- Components: PascalCase with `Component` suffix, selector prefixed\n  `my-` (`my-video-miniature`)\n- Path aliases: `@app/*` → `src/app/*`,\n  `@root-helpers/*` → `src/root-helpers/*`\n\n### Internationalization\n\n- Source locale: `en` (base href `/client/en-US/`)\n- Translation files: XLIFF format in `src/locale/`\n- Merge tool: `@peertube/xliffmerge` (config: `.xliffmerge.json`)\n- Use Angular `$localize` / `i18n` attributes; do NOT use raw strings\n  for user-visible text\n\n## Architecture Notes\n\n```\n┌────────────────────────────────────────────────────────┐\n│                 Angular SPA (client/)                   │\n│                                                         │\n│  ┌──────────┐  ┌──────────────┐  ┌──────────────────┐  │\n│  │  Routes   │  │  Core        │  │  Shared          │  │\n│  │ (+about,  │  │ (auth, REST, │  │ (forms, video    │  │\n│  │  +admin,  │──│  plugins,    │──│  miniature,      │  │\n│  │  +videos) │  │  server,     │  │  moderation...)  │  │\n│  │           │  │  theme)      │  │                  │  │\n│  └──────────┘  └──────┬───────┘  └──────────────────┘  │\n│                        │                                │\n│  ┌─────────────────────▼────────────────────────────┐   │\n│  │           root-helpers (no Angular dep)           │   │\n│  │  logger, storage, plugins-manager, theme, i18n   │   │\n│  └──────────────────────────────────────────────────┘   │\n│                                                         │\n│  ┌─────────────────────────────────────────────────┐    │\n│  │         standalone/ (Vite builds)               │    │\n│  │  player/ │ embed-player-api/ │ videos/embed     │    │\n│  └─────────────────────────────────────────────────┘    │\n└────────────────────────┬────────────────────────────────┘\n                         │ HTTP (REST API)\n                         ▼\n              ┌──────────────────────┐\n              │  Express Backend     │\n              │  (:9000 /api/v1/*)   │\n              └──────────────────────┘\n```\n\n- **Lazy loading**: Each `+feature/` folder exports route configs\n  loaded via `loadChildren` in `app.routes.ts`\n- **Core services**: Singletons bootstrapped in `main.ts` via\n  `getCoreProviders()` — auth, REST client, server config polling,\n  plugin hooks, theme manager\n- **Plugin hooks**: Client-side plugins register via\n  `HooksService` / `PluginService` in `core/plugins/`\n- **State management**: No dedicated store library; services hold\n  state, components subscribe via RxJS observables\n- **UI framework**: Bootstrap 5 + PrimeNG + ng-bootstrap;\n  global SCSS in `src/sass/`\n- **Video player**: Custom build in `standalone/player/` using\n  Video.js + HLS.js + P2P Media Loader; embedded via\n  `standalone/videos/embed.html`\n\n## Agent Guardrails\n\n### Files agents must NOT modify\n\n- `src/locale/*.xlf` — Generated translation files; updated via\n  `npm run i18n:update` only\n- `dist/` — Build output; never edit manually\n- `node_modules/` — Managed by pnpm\n- `.angular/` — Angular build cache\n\n### Required checks before pushing\n\n1. `cd client && npm run lint` must pass (TS + SCSS)\n2. Production build must succeed: `npm run build:client`\n   (from repo root)\n3. If new user-visible strings added: extract with\n   `npm run i18n:create-custom-files` and verify XLIFF\n\n### Boundaries\n\n- Do not import from `server/` — the client communicates with the\n  backend exclusively via the REST API\n- Do not import Angular-specific code in `root-helpers/` or\n  `standalone/` — these must remain framework-agnostic\n- Shared API types come from `@peertube/peertube-models` and\n  `@peertube/peertube-core-utils` (workspace packages)\n- Do not add new npm dependencies without explicit approval\n\n## Further Reading\n\n- [../support/doc/plugins/guide.md](../support/doc/plugins/guide.md)\n  — Plugin & theme development (client hooks)\n- [src/standalone/embed-player-api/README.md](src/standalone/embed-player-api/README.md)\n  — Embed player API documentation\n- [../support/doc/api/embeds.md](../support/doc/api/embeds.md)\n  — Embed integration guide\n- [../AGENTS.md](../AGENTS.md)\n  — Root project AGENTS.md (server, build, CI, testing)\n","AGENTS.md":"# Project Overview\n\nPeerTube is an open-source, ActivityPub-federated video streaming platform\nthat uses P2P technology directly in web browsers. Developed by Framasoft\nunder the AGPL-3.0 license, it provides a decentralized alternative to\ncentralized video platforms. The server is a Node.js/Express API with a\nSequelize ORM (PostgreSQL), background job processing (BullMQ/Redis),\nActivityPub federation, and an Angular SPA client. Video transcoding is\nhandled via FFmpeg, with optional distributed runners.\n\n## Repository Structure\n\n- **apps/** — Standalone CLI applications (`peertube-cli`, `peertube-runner`)\n- **client/** — Angular frontend SPA (separate build system)\n- **config/** — YAML configuration files for dev, test, and production\n- **packages/** — Shared workspace packages (monorepo):\n  - `core-utils/` — Shared pure-JS utilities\n  - `ffmpeg/` — FFmpeg wrapper library\n  - `models/` — Shared TypeScript interfaces and API types\n  - `node-utils/` — Node.js-specific helpers\n  - `server-commands/` — HTTP client helpers used by tests\n  - `tests/` — Full test suite (API, CLI, plugins, feeds, etc.)\n  - `transcription/` — Speech-to-text engine integration\n  - `transcription-devtools/` — Transcription benchmarking tools\n  - `types-generator/` — Generates the public `@peertube/peertube-types`\n    package\n  - `typescript-utils/` — Generic TypeScript helpers\n- **scripts/** — Build, CI, dev, release, and i18n shell scripts\n- **server/** — Backend entry point and core application code\n  - `server.ts` — Process entry point\n  - `core/controllers/` — Express route handlers (API, ActivityPub,\n    feeds, tracker)\n  - `core/models/` — Sequelize database models (14 categories)\n  - `core/lib/` — Business logic (transcoding, live, job queue,\n    ActivityPub, plugins, runners, notifications, etc.)\n  - `core/middlewares/` — Auth, rate-limiting, validation, caching, CSP\n  - `core/helpers/` — Utility functions and custom validators\n  - `core/initializers/` — App bootstrap, constants, DB migrations,\n    config loading\n  - `core/types/` — Internal TypeScript type augmentations\n- **support/** — Documentation, Docker, Nginx configs, OpenAPI spec\n\n## Build & Development Commands\n\n### Prerequisites\n\n- Node.js >= 22.x\n- pnpm >= 12 (do **not** use npm or yarn for install)\n- PostgreSQL >= 14 with `pg_trgm` and `unaccent` extensions\n- Redis >= 6.x\n- FFmpeg >= 4.3\n- Python >= 3.8 (for some test tooling)\n\n### Install dependencies\n\n```bash\npnpm install --frozen-lockfile\n```\n\n### Build\n\n```bash\n# Build server only (backend work)\nnpm run build:server\n\n# Build full application (server + client)\nnpm run build\n\n# Build tests\nnpm run build:tests\n\n# Build individual apps\nnpm run build:peertube-cli\nnpm run build:peertube-runner\n```\n\n### Development\n\n```bash\n# Server-only with hot reload (recommended for backend work)\nnpm run dev:server        # http://localhost:9000\n\n# Full stack (server + Angular client)\nnpm run dev               # server :9000, client :3000\n\n# Dev credentials: root / test\n```\n\n### Lint & type-check\n\n```bash\n# Full lint (oxlint + OpenAPI validation)\nnpm run lint\n\n# Oxlint only\nnpm run oxlint\n\n# Validate OpenAPI spec\nnpm run swagger-cli -- validate support/doc/api/openapi.yaml\n\n# TypeScript compilation check\nnpm run tsc -b server/tsconfig.json\n```\n\n### Run in production\n\n```bash\nnpm run start              # server + client\nnpm run start:server       # server only (--no-client)\n```\n\n## Code Style & Conventions\n\n### Formatting (enforced by Oxlint)\n\n| Rule                | Value                                 |\n|---------------------|---------------------------------------|\n| Semicolons          | **never** (`@stylistic/semi`)         |\n| Max line length     | 140 characters                        |\n| Quotes              | Single quotes (TypeScript default)    |\n| Array brackets      | Spaces inside `[ 'a', 'b' ]`         |\n| Trailing newline    | Required (`eol-last`)                 |\n| Indentation         | 2 spaces (TypeScript convention)      |\n\n### Naming patterns\n\n- Database models: `VideoModel`, `UserModel` — PascalCase + `Model` suffix\n- Internal type aliases: `MVideo`, `MVideoWithChannel` — `M` prefix for\n  Sequelize model types with specific association requirements\n- Controllers: one file per resource, registered in parent `index.ts`\n- Validators: mirror controller structure under\n  `server/core/middlewares/validators/`\n\n### Controller pattern\n\n```typescript\nimport express from 'express'\nimport { apiRateLimiter, asyncMiddleware } from '../../middlewares/index.js'\n\nconst router = express.Router()\nrouter.use(apiRateLimiter)  // always include rate limiting\n\nrouter.get('/:id',\n  validationMiddleware,     // always validate inputs\n  asyncMiddleware(handler)  // always wrap async handlers\n)\n```\n\nSecondary processes (`--role=secondary`) serve every route. A route that needs a state only the primary\nprocess has (its file system, data kept in its memory, live sessions, the tracker...) must start with the\n`primaryOnly` middleware, before any side effect: a secondary answers `421` and nginx replays the request on\nthe primary. Requests whose body nginx streams (`proxy_request_buffering off` locations) cannot be replayed:\nroute them to `backend` in the `$peertube_pool` map of `support/nginx/peertube`.\n\n### Commit messages\n\nNo formal commit-message template.\n\n### Oxlint config\n\nDefined in `oxlint.config.mjs`. Applies to `server/**/*.ts`,\n`scripts/**/*.ts`, `packages/**/*.ts`, `apps/**/*.ts`. The `client/`\ndirectory has its own lint config.\n\n## Architecture Notes\n\n```\n                  ┌──────────────────────────────────────────┐\n                  │            Reverse Proxy (Nginx)         │\n                  └──────────────┬───────────────────────────┘\n                                 │\n              ┌──────────────────▼──────────────────────┐\n              │          Express.js API Server           │\n              │  (server/server.ts → core/controllers/)  │\n              │                                          │\n              │  ┌─────────┐ ┌──────────┐ ┌──────────┐  │\n              │  │  REST   │ │Activity- │ │  Feeds/  │  │\n              │  │  API    │ │  Pub     │ │  oEmbed  │  │\n              │  │  /api/* │ │  /inbox  │ │  /feeds  │  │\n              │  └────┬────┘ └────┬─────┘ └────┬─────┘  │\n              │       │           │             │        │\n              │  ┌────▼───────────▼─────────────▼────┐  │\n              │  │       Middleware Pipeline          │  │\n              │  │  (auth, validators, rate-limit)    │  │\n              │  └────────────────┬───────────────────┘  │\n              │                   │                      │\n              │  ┌────────────────▼───────────────────┐  │\n              │  │        Business Logic (lib/)       │  │\n              │  │  videos, live, transcoding,        │  │\n              │  │  federation, notifications,        │  │\n              │  │  plugins, runners                  │  │\n              │  └──┬──────────┬──────────────┬───┘   │\n              └─────┼──────────┼──────────────┼───────┘\n                    │          │              │\n          ┌────────▼──┐ ┌─────▼─────┐ ┌──────▼──────┐\n          │PostgreSQL │ │   Redis   │ │  FFmpeg /   │\n          │(Sequelize)│ │ (BullMQ   │ │  Runners    │\n          │           │ │  + cache) │ │             │\n          └───────────┘ └───────────┘ └─────────────┘\n```\n\n**Startup sequence** (`server/server.ts`):\n\n1. Register OpenTelemetry tracing\n2. Pre-init checks (config, FFmpeg, Node.js version)\n3. Connect to PostgreSQL, run migrations\n4. Initialize Sequelize models and load i18n\n5. Configure Express middleware stack (proxy trust, CSP, CORS,\n   rate-limiting, OAuth2 auth, express-validator)\n6. Mount route controllers and start listening\n\n**Key data flows**:\n\n- **Video upload**: REST API → validator middleware → `lib/video.ts` →\n  job queue → FFmpeg transcoding → HLS/web-video files → object\n  storage or local filesystem\n- **Federation**: Incoming ActivityPub requests → signature\n  verification → `lib/activitypub/` processors → local DB updates +\n  outgoing fan-out\n- **Live streaming**: RTMP ingest → FFmpeg segmenter → HLS manifest →\n  P2P delivery via WebSocket tracker\n\n## Testing Strategy\n\n### Test framework\n\n- **Mocha** for all server/API tests\n- **GNU Parallel** for running test files concurrently in CI\n- Tests live in `packages/tests/src/` (TypeScript source) and are\n  compiled to `packages/tests/dist/`\n\n### Preparation\n\n```bash\n# Create PostgreSQL superuser for test DB management\nsudo -u postgres createuser $(whoami) --createdb --superuser\n\n# Clean test databases\nnpm run clean:server:test\n\n# Build server + tests\nnpm run build:server\nnpm run build:tests\n```\n\n### Running tests\n\n```bash\n# Full suite (slow, ~45-60 min)\nnpm run test\n\n# Run a specific CI suite\nnpm run ci -- api-check-params-search       # check-params, search\nnpm run ci -- api-videos-1 | api-videos-2   # videos, split in 2 shards balanced by duration\nnpm run ci -- api-server                    # server\nnpm run ci -- api-live-scalability          # live, horizontal-scalability\nnpm run ci -- api-users-stats               # users, stats\nnpm run ci -- api-moderation-notifications  # moderation, notifications\nnpm run ci -- api-federation                # activitypub, redundancy\nnpm run ci -- api-object-storage            # object-storage\nnpm run ci -- api-transcoding-1 | api-transcoding-2  # transcoding + runners, split in 2 shards\nnpm run ci -- client      # feeds, client, misc-endpoints, plugins\nnpm run ci -- cli-plugin  # CLI and plugin tests\nnpm run ci -- lint        # OXlint + OpenAPI validation + client lint\nnpm run ci -- transcription\nnpm run ci -- external-plugins\n\n# Run a single test file\nnpm run mocha -- --timeout 30000 --exit --bail \\\n  packages/tests/src/api/videos/single-server.ts\n```\n\n### External test dependencies (Docker)\n\nSome tests require these containers:\n\n```bash\ndocker run -p 9444:8000 -e S3BACKEND=mem -e REMOTE_MANAGEMENT_DISABLE=1 \\\n  -e SCALITY_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \\\n  -e SCALITY_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \\\n  ghcr.io/scality/cloudserver:9.3.20\ndocker run -p 10389:10389 chocobozzz/docker-test-openldap\ndocker run -p 8082:8080 \\\n  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \\\n  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \\\n  chocobozzz/peertube-tests-keycloak\n```\n\n### CI pipeline\n\nGitHub Actions (`.github/workflows/test.yml`), Ubuntu 22.04, Node.js\n22.x. Matrix strategy runs suites in parallel: `types-package`,\n`client`, the `api-*` suites listed above, `cli-plugin`, `lint`, `transcription`,\n`external-plugins`.\n\nServices provisioned per job: PostgreSQL 10, Redis, LDAP, S3 Ninja,\nKeycloak.\n\n### Environment variables for tests\n\n| Variable                                   | Purpose                     |\n|--------------------------------------------|-----------------------------|\n| `DISABLE_HTTP_IMPORT_TESTS=true`           | Skip flaky HTTP import tests|\n| `DISABLE_HTTP_YOUTUBE_IMPORT_TESTS=true`   | Skip YouTube import tests   |\n| `ENABLE_OBJECT_STORAGE_TESTS=true`         | Enable S3 tests             |\n\n## Security & Compliance\n\n- **License**: AGPL-3.0 — all network-facing modifications must be\n  published under the same license.\n- **Secrets**: The `secrets.peertube` key in `config/*.yaml` must be\n  generated via `openssl rand -hex 32`. Never commit secrets; use\n  `config/local-*.json` overrides (gitignored) or environment variables.\n- **OAuth2**: Access tokens expire in 1 day; refresh tokens in 2 weeks\n  (configurable in `config/default.yaml`).\n- **Rate limiting**: All API endpoints are rate-limited by default\n  (`apiRateLimiter` middleware). Specific limits per category (login,\n  signup, ActivityPub, etc.) are configured in `config/default.yaml`.\n- **CSP**: Content-Security-Policy headers are configurable and applied\n  via `server/core/middlewares/csp.ts`.\n- **Input validation**: Every controller uses express-validator\n  middleware defined in `server/core/middlewares/validators/`.\n- **Vulnerability reporting**: `peertube-security@framasoft.org` —\n  see `SECURITY.md`.\n- **Dependency scanning**: No automated scanner configuration found in\n  the repo.\n\n## Agent Guardrails\n\n### Files and directories agents must NOT modify\n\n- `config/local-*.json` — User-local config overrides (gitignored)\n- `config/production.yaml.example` — Template; changes need release\n  coordination\n- `server/core/initializers/migrations/` — Existing migration files are\n  immutable once released; only append new ones\n- `pnpm-lock.yaml` — Regenerated by `pnpm install`; never edit manually\n- `support/doc/api/openapi.yaml` — Must stay in sync with controllers;\n  validate with `npm run swagger-cli -- validate`\n\n### Required checks before pushing\n\n1. `npm run build:server` must succeed\n2. `npm run lint` must pass\n3. If API surface changed: `npm run swagger-cli -- validate\n   support/doc/api/openapi.yaml`\n4. If database schema changed: create a new migration file **and**\n   increment `LAST_MIGRATION_VERSION` in\n   `server/core/initializers/constants.ts`\n\n### Boundaries\n\n- Do not run `pnpm install` without `--frozen-lockfile`\n- Do not use `npm install` or `yarn` — this project uses **pnpm**\n- Do not add dependencies without explicit approval\n- Do not modify test Docker images or CI service definitions without\n  review\n- Maximum concurrency for background jobs is configured in constants;\n  do not change without benchmarking\n\n## Extensibility Hooks\n\n### Plugin system\n\nPeerTube supports server and client plugins via a hook-based\narchitecture. Plugins register `filter`, `action`, and `static`\nhooks—see `support/doc/plugins/guide.md`.\n\n- Plugin names follow `peertube-plugin-*` (themes: `peertube-theme-*`)\n- Server hooks are registered in `server/core/lib/plugins/`\n- Plugin management API: `/api/v1/plugins`\n- Install/uninstall scripts: `npm run plugin:install`,\n  `npm run plugin:uninstall`\n\n### Configuration\n\nAll runtime configuration is in YAML under `config/`. Local overrides\nuse `config/local-*.json` files (gitignored). Key env vars:\n\n| Variable              | Purpose                              |\n|-----------------------|--------------------------------------|\n| `NODE_ENV`            | `production`, `development`, `test`  |\n| `NODE_CONFIG_DIR`     | Override config directory             |\n| `LOGGER_LEVEL`        | `debug`, `info`, `warn`, `error`     |\n| `PT_INITIAL_ROOT_PASSWORD` | Set root password on first run  |\n\n### Runners (distributed transcoding)\n\nExternal `peertube-runner` processes poll the API for transcoding jobs.\nConfigured in `server/core/lib/runners/` and managed through the\n`/api/v1/runners` endpoints.\n\n### OpenTelemetry\n\nTracing and metrics are instrumented via `@opentelemetry/*` packages.\nExport to an OTLP endpoint like Jaeger (tracing) or Prometheus (metrics) is configurable in\n`config/default.yaml` under the `open_telemetry` key.\n\n## Further Reading\n\n- [support/doc/development/server.md](support/doc/development/server.md)\n  — Server code conventions and new-feature walkthrough\n- [Horizontal scalability](https://docs.joinpeertube.org/maintain/horizontal-scalability)\n  — Running several processes (`--role=secondary`) for one instance\n- [support/doc/development/tests.md](support/doc/development/tests.md)\n  — Test setup and execution guide\n- [support/doc/plugins/guide.md](support/doc/plugins/guide.md)\n  — Plugin & theme development guide\n- [support/doc/api/openapi.yaml](support/doc/api/openapi.yaml)\n  — OpenAPI 3.0 specification\n- [support/doc/production.md](support/doc/production.md)\n  — Production deployment guide\n- [support/doc/docker.md](support/doc/docker.md)\n  — Docker deployment guide\n- [support/doc/development/lib.md](support/doc/development/lib.md)\n  — Library / business-logic documentation\n- [SECURITY.md](SECURITY.md) — Vulnerability disclosure policy\n- [FAQ.md](FAQ.md) — Frequently asked questions\n","packages/ffmpeg/package.json":"{\n  \"name\": \"@peertube/peertube-ffmpeg\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","packages/models/tsconfig.json":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  }\n}\n","packages/models/tsconfig.types.json":"{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../types-generator/dist-tmp/peertube-models\",\n    \"tsBuildInfoFile\": \"../types-generator/dist-tmp/peertube-models/.tsbuildinfo\",\n    \"stripInternal\": true,\n    \"removeComments\": false,\n    \"emitDeclarationOnly\": true\n  }\n}\n","packages/node-utils/tsconfig.json":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../core-utils\" }\n  ]\n}\n","packages/node-utils/package.json":"{\n  \"name\": \"@peertube/peertube-node-utils\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","packages/server-commands/package.json":"{\n  \"name\": \"@peertube/peertube-server-commands\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {\n    \"@aws-sdk/client-s3\": \"^3.1161.0\",\n    \"@types/superagent\": \"^8.1.11\",\n    \"@types/supertest\": \"^7.2.1\",\n    \"supertest\": \"^7.3.1\"\n  },\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {\n    \"@peertube/peertube-core-utils\": \"workspace:*\",\n    \"@peertube/peertube-models\": \"workspace:*\",\n    \"@peertube/peertube-node-utils\": \"workspace:*\",\n    \"@peertube/peertube-typescript-utils\": \"workspace:*\"\n  }\n}\n","packages/models/package.json":"{\n  \"name\": \"@peertube/peertube-models\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"type\": \"module\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","packages/server-commands/tsconfig.json":"# Server-commands Skill\n\nPath: `packages/server-commands/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/server-commands/tsconfig.json)","packages/tests/package.json":"# Tests Skill\n\nPath: `packages/tests/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/package.json)","packages/tests/tsconfig.json":"# Tests Skill\n\nPath: `packages/tests/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/tsconfig.json)","packages/transcription-devtools/README.md":"# transcription-devtools Documentation\n\nPath: `packages/transcription-devtools/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/README.md)","packages/transcription-devtools/package.json":"# Transcription-devtools Skill\n\nPath: `packages/transcription-devtools/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/package.json)","packages/transcription-devtools/tsconfig.json":"# Transcription-devtools Skill\n\nPath: `packages/transcription-devtools/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/tsconfig.json)","packages/transcription/README.md":"# transcription Documentation\n\nPath: `packages/transcription/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/README.md)","packages/transcription/package.json":"# Transcription Skill\n\nPath: `packages/transcription/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/package.json)","packages/transcription/tsconfig.json":"# Transcription Skill\n\nPath: `packages/transcription/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/tsconfig.json)","packages/transcription/tsconfig.types.json":"# Transcription Skill\n\nPath: `packages/transcription/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/tsconfig.types.json)","packages/types-generator/README.md":"# types-generator Documentation\n\nPath: `packages/types-generator/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/README.md)","packages/types-generator/package.json":"# Types-generator Skill\n\nPath: `packages/types-generator/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/package.json)","packages/types-generator/tsconfig.dist-tmp.json":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.dist-tmp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.dist-tmp.json)","packages/types-generator/tsconfig.json":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.json)","packages/types-generator/tsconfig.types.json":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.types.json)","packages/typescript-utils/package.json":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/package.json)","packages/typescript-utils/tsconfig.json":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/tsconfig.json)","packages/typescript-utils/tsconfig.types.json":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/tsconfig.types.json)","support/doc/plugins/guide.md":"# Plugins Skill\n\nPath: `support/doc/plugins/guide.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/support/doc/plugins/guide.md)","packages/tests/fixtures/peertube-plugin-test-broken/package.json":"# Peertube-plugin-test-broken Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-broken/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-broken/package.json)","packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json":"# Peertube-plugin-test-css-sourcemap Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json)","packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json":"# Peertube-plugin-test-external-auth-four Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json)","packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json":"# Peertube-plugin-test-external-auth-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json)","packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json":"# Peertube-plugin-test-external-auth-three Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json)","packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json":"# Peertube-plugin-test-external-auth-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json)","packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json":"# Peertube-plugin-test-filter-translations Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json)","packages/tests/fixtures/peertube-plugin-test-five/package.json":"# Peertube-plugin-test-five Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-five/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-five/package.json)","packages/tests/fixtures/peertube-plugin-test-four/package.json":"# Peertube-plugin-test-four Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-four/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-four/package.json)","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json":"# Peertube-plugin-test-id-pass-auth-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json)","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json":"# Peertube-plugin-test-id-pass-auth-three Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json)","packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json":"# Peertube-plugin-test-id-pass-auth-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json)","packages/tests/fixtures/peertube-plugin-test-native/package.json":"# Peertube-plugin-test-native Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-native/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-native/package.json)","packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json":"# Peertube-plugin-test-podcast-custom-tags Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json)","packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json":"# Peertube-plugin-test-secondary-failure Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json)","packages/tests/fixtures/peertube-plugin-test-secondary/package.json":"# Peertube-plugin-test-secondary Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-secondary/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-secondary/package.json)","packages/tests/fixtures/peertube-plugin-test-seven/package.json":"# Peertube-plugin-test-seven Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-seven/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-seven/package.json)","packages/tests/fixtures/peertube-plugin-test-six/package.json":"# Peertube-plugin-test-six Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-six/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-six/package.json)","packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json":"# Peertube-plugin-test-slow-live-setup Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json)","packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json":"# Peertube-plugin-test-transcoding-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json)","packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json":"# Peertube-plugin-test-transcoding-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json)","packages/tests/fixtures/peertube-plugin-test-transcription/package.json":"# Peertube-plugin-test-transcription Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcription/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcription/package.json)","packages/tests/fixtures/peertube-plugin-test-unloading/package.json":"# Peertube-plugin-test-unloading Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-unloading/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-unloading/package.json)","packages/tests/fixtures/peertube-plugin-test-upload-file/package.json":"# Peertube-plugin-test-upload-file Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-upload-file/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-upload-file/package.json)","packages/tests/fixtures/peertube-plugin-test-video-constants/package.json":"# Peertube-plugin-test-video-constants Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-video-constants/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-video-constants/package.json)","packages/tests/fixtures/peertube-plugin-test-websocket/package.json":"# Peertube-plugin-test-websocket Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-websocket/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-websocket/package.json)","packages/tests/fixtures/peertube-plugin-test/package.json":"# Peertube-plugin-test Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test/package.json)","packages/types-generator/src/client/tsconfig.types.json":"# Client Skill\n\nPath: `packages/types-generator/src/client/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/src/client/tsconfig.types.json)","packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json)","packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json)","packages/tests/fixtures/ap-json/mastodon/bad-public-key.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-public-key.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-public-key.json)","packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json)","packages/tests/fixtures/ap-json/mastodon/create.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/create.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create.json)","packages/tests/fixtures/ap-json/mastodon/http-signature.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/http-signature.json)","packages/tests/fixtures/ap-json/mastodon/public-key.json":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/public-key.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/public-key.json)","packages/tests/fixtures/ap-json/peertube/announce-without-context.json":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/announce-without-context.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/announce-without-context.json)","packages/tests/fixtures/ap-json/peertube/invalid-keys.json":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/invalid-keys.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/invalid-keys.json)","packages/tests/fixtures/ap-json/peertube/keys.json":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/keys.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/keys.json)","packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json)","packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json)","packages/tests/fixtures/peertube-plugin-test/languages/fr.json":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test/languages/fr.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test/languages/fr.json)","packages/tests/fixtures/transcription/videos/README.md":"# videos Documentation\n\nPath: `packages/tests/fixtures/transcription/videos/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/transcription/videos/README.md)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Project Overview\n\nPeerTube is an open-source, ActivityPub-federated video streaming platform\nthat uses P2P technology directly in web browsers. Developed by Framasoft\nunder the AGPL-3.0 license, it provides a decentralized alternative to\ncentralized video platforms. The server is a Node.js/Express API with a\nSequelize ORM (PostgreSQL), background job processing (BullMQ/Redis),\nActivityPub federation, and an Angular SPA client. Video transcoding is\nhandled via FFmpeg, with optional distributed runners.\n\n## Repository Structure\n\n- **apps/** — Standalone CLI applications (`peertube-cli`, `peertube-runner`)\n- **client/** — Angular frontend SPA (separate build system)\n- **config/** — YAML configuration files for dev, test, and production\n- **packages/** — Shared workspace packages (monorepo):\n  - `core-utils/` — Shared pure-JS utilities\n  - `ffmpeg/` — FFmpeg wrapper library\n  - `models/` — Shared TypeScript interfaces and API types\n  - `node-utils/` — Node.js-specific helpers\n  - `server-commands/` — HTTP client helpers used by tests\n  - `tests/` — Full test suite (API, CLI, plugins, feeds, etc.)\n  - `transcription/` — Speech-to-text engine integration\n  - `transcription-devtools/` — Transcription benchmarking tools\n  - `types-generator/` — Generates the public `@peertube/peertube-types`\n    package\n  - `typescript-utils/` — Generic TypeScript helpers\n- **scripts/** — Build, CI, dev, release, and i18n shell scripts\n- **server/** — Backend entry point and core application code\n  - `server.ts` — Process entry point\n  - `core/controllers/` — Express route handlers (API, ActivityPub,\n    feeds, tracker)\n  - `core/models/` — Sequelize database models (14 categories)\n  - `core/lib/` — Business logic (transcoding, live, job queue,\n    ActivityPub, plugins, runners, notifications, etc.)\n  - `core/middlewares/` — Auth, rate-limiting, validation, caching, CSP\n  - `core/helpers/` — Utility functions and custom validators\n  - `core/initializers/` — App bootstrap, constants, DB migrations,\n    config loading\n  - `core/types/` — Internal TypeScript type augmentations\n- **support/** — Documentation, Docker, Nginx configs, OpenAPI spec\n\n## Build & Development Commands\n\n### Prerequisites\n\n- Node.js >= 22.x\n- pnpm >= 12 (do **not** use npm or yarn for install)\n- PostgreSQL >= 14 with `pg_trgm` and `unaccent` extensions\n- Redis >= 6.x\n- FFmpeg >= 4.3\n- Python >= 3.8 (for some test tooling)\n\n### Install dependencies\n\n```bash\npnpm install --frozen-lockfile\n```\n\n### Build\n\n```bash\n# Build server only (backend work)\nnpm run build:server\n\n# Build full application (server + client)\nnpm run build\n\n# Build tests\nnpm run build:tests\n\n# Build individual apps\nnpm run build:peertube-cli\nnpm run build:peertube-runner\n```\n\n### Development\n\n```bash\n# Server-only with hot reload (recommended for backend work)\nnpm run dev:server        # http://localhost:9000\n\n# Full stack (server + Angular client)\nnpm run dev               # server :9000, client :3000\n\n# Dev credentials: root / test\n```\n\n### Lint & type-check\n\n```bash\n# Full lint (oxlint + OpenAPI validation)\nnpm run lint\n\n# Oxlint only\nnpm run oxlint\n\n# Validate OpenAPI spec\nnpm run swagger-cli -- validate support/doc/api/openapi.yaml\n\n# TypeScript compilation check\nnpm run tsc -b server/tsconfig.json\n```\n\n### Run in production\n\n```bash\nnpm run start              # server + client\nnpm run start:server       # server only (--no-client)\n```\n\n## Code Style & Conventions\n\n### Formatting (enforced by Oxlint)\n\n| Rule                | Value                                 |\n|---------------------|---------------------------------------|\n| Semicolons          | **never** (`@stylistic/semi`)         |\n| Max line length     | 140 characters                        |\n| Quotes              | Single quotes (TypeScript default)    |\n| Array brackets      | Spaces inside `[ 'a', 'b' ]`         |\n| Trailing newline    | Required (`eol-last`)                 |\n| Indentation         | 2 spaces (TypeScript convention)      |\n\n### Naming patterns\n\n- Database models: `VideoModel`, `UserModel` — PascalCase + `Model` suffix\n- Internal type aliases: `MVideo`, `MVideoWithChannel` — `M` prefix for\n  Sequelize model types with specific association requirements\n- Controllers: one file per resource, registered in parent `index.ts`\n- Validators: mirror controller structure under\n  `server/core/middlewares/validators/`\n\n### Controller pattern\n\n```typescript\nimport express from 'express'\nimport { apiRateLimiter, asyncMiddleware } from '../../middlewares/index.js'\n\nconst router = express.Router()\nrouter.use(apiRateLimiter)  // always include rate limiting\n\nrouter.get('/:id',\n  validationMiddleware,     // always validate inputs\n  asyncMiddleware(handler)  // always wrap async handlers\n)\n```\n\nSecondary processes (`--role=secondary`) serve every route. A route that needs a state only the primary\nprocess has (its file system, data kept in its memory, live sessions, the tracker...) must start with the\n`primaryOnly` middleware, before any side effect: a secondary answers `421` and nginx replays the request on\nthe primary. Requests whose body nginx streams (`proxy_request_buffering off` locations) cannot be replayed:\nroute them to `backend` in the `$peertube_pool` map of `support/nginx/peertube`.\n\n### Commit messages\n\nNo formal commit-message template.\n\n### Oxlint config\n\nDefined in `oxlint.config.mjs`. Applies to `server/**/*.ts`,\n`scripts/**/*.ts`, `packages/**/*.ts`, `apps/**/*.ts`. The `client/`\ndirectory has its own lint config.\n\n## Architecture Notes\n\n```\n                  ┌──────────────────────────────────────────┐\n                  │            Reverse Proxy (Nginx)         │\n                  └──────────────┬───────────────────────────┘\n                                 │\n              ┌──────────────────▼──────────────────────┐\n              │          Express.js API Server           │\n              │  (server/server.ts → core/controllers/)  │\n              │                                          │\n              │  ┌─────────┐ ┌──────────┐ ┌──────────┐  │\n              │  │  REST   │ │Activity- │ │  Feeds/  │  │\n              │  │  API    │ │  Pub     │ │  oEmbed  │  │\n              │  │  /api/* │ │  /inbox  │ │  /feeds  │  │\n              │  └────┬────┘ └────┬─────┘ └────┬─────┘  │\n              │       │           │             │        │\n              │  ┌────▼───────────▼─────────────▼────┐  │\n              │  │       Middleware Pipeline          │  │\n              │  │  (auth, validators, rate-limit)    │  │\n              │  └────────────────┬───────────────────┘  │\n              │                   │                      │\n              │  ┌────────────────▼───────────────────┐  │\n              │  │        Business Logic (lib/)       │  │\n              │  │  videos, live, transcoding,        │  │\n              │  │  federation, notifications,        │  │\n              │  │  plugins, runners                  │  │\n              │  └──┬──────────┬──────────────┬───┘   │\n              └─────┼──────────┼──────────────┼───────┘\n                    │          │              │\n          ┌────────▼──┐ ┌─────▼─────┐ ┌──────▼──────┐\n          │PostgreSQL │ │   Redis   │ │  FFmpeg /   │\n          │(Sequelize)│ │ (BullMQ   │ │  Runners    │\n          │           │ │  + cache) │ │             │\n          └───────────┘ └───────────┘ └─────────────┘\n```\n\n**Startup sequence** (`server/server.ts`):\n\n1. Register OpenTelemetry tracing\n2. Pre-init checks (config, FFmpeg, Node.js version)\n3. Connect to PostgreSQL, run migrations\n4. Initialize Sequelize models and load i18n\n5. Configure Express middleware stack (proxy trust, CSP, CORS,\n   rate-limiting, OAuth2 auth, express-validator)\n6. Mount route controllers and start listening\n\n**Key data flows**:\n\n- **Video upload**: REST API → validator middleware → `lib/video.ts` →\n  job queue → FFmpeg transcoding → HLS/web-video files → object\n  storage or local filesystem\n- **Federation**: Incoming ActivityPub requests → signature\n  verification → `lib/activitypub/` processors → local DB updates +\n  outgoing fan-out\n- **Live streaming**: RTMP ingest → FFmpeg segmenter → HLS manifest →\n  P2P delivery via WebSocket tracker\n\n## Testing Strategy\n\n### Test framework\n\n- **Mocha** for all server/API tests\n- **GNU Parallel** for running test files concurrently in CI\n- Tests live in `packages/tests/src/` (TypeScript source) and are\n  compiled to `packages/tests/dist/`\n\n### Preparation\n\n```bash\n# Create PostgreSQL superuser for test DB management\nsudo -u postgres createuser $(whoami) --createdb --superuser\n\n# Clean test databases\nnpm run clean:server:test\n\n# Build server + tests\nnpm run build:server\nnpm run build:tests\n```\n\n### Running tests\n\n```bash\n# Full suite (slow, ~45-60 min)\nnpm run test\n\n# Run a specific CI suite\nnpm run ci -- api-check-params-search       # check-params, search\nnpm run ci -- api-videos-1 | api-videos-2   # videos, split in 2 shards balanced by duration\nnpm run ci -- api-server                    # server\nnpm run ci -- api-live-scalability          # live, horizontal-scalability\nnpm run ci -- api-users-stats               # users, stats\nnpm run ci -- api-moderation-notifications  # moderation, notifications\nnpm run ci -- api-federation                # activitypub, redundancy\nnpm run ci -- api-object-storage            # object-storage\nnpm run ci -- api-transcoding-1 | api-transcoding-2  # transcoding + runners, split in 2 shards\nnpm run ci -- client      # feeds, client, misc-endpoints, plugins\nnpm run ci -- cli-plugin  # CLI and plugin tests\nnpm run ci -- lint        # OXlint + OpenAPI validation + client lint\nnpm run ci -- transcription\nnpm run ci -- external-plugins\n\n# Run a single test file\nnpm run mocha -- --timeout 30000 --exit --bail \\\n  packages/tests/src/api/videos/single-server.ts\n```\n\n### External test dependencies (Docker)\n\nSome tests require these containers:\n\n```bash\ndocker run -p 9444:8000 -e S3BACKEND=mem -e REMOTE_MANAGEMENT_DISABLE=1 \\\n  -e SCALITY_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \\\n  -e SCALITY_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \\\n  ghcr.io/scality/cloudserver:9.3.20\ndocker run -p 10389:10389 chocobozzz/docker-test-openldap\ndocker run -p 8082:8080 \\\n  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \\\n  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \\\n  chocobozzz/peertube-tests-keycloak\n```\n\n### CI pipeline\n\nGitHub Actions (`.github/workflows/test.yml`), Ubuntu 22.04, Node.js\n22.x. Matrix strategy runs suites in parallel: `types-package`,\n`client`, the `api-*` suites listed above, `cli-plugin`, `lint`, `transcription`,\n`external-plugins`.\n\nServices provisioned per job: PostgreSQL 10, Redis, LDAP, S3 Ninja,\nKeycloak.\n\n### Environment variables for tests\n\n| Variable                                   | Purpose                     |\n|--------------------------------------------|-----------------------------|\n| `DISABLE_HTTP_IMPORT_TESTS=true`           | Skip flaky HTTP import tests|\n| `DISABLE_HTTP_YOUTUBE_IMPORT_TESTS=true`   | Skip YouTube import tests   |\n| `ENABLE_OBJECT_STORAGE_TESTS=true`         | Enable S3 tests             |\n\n## Security & Compliance\n\n- **License**: AGPL-3.0 — all network-facing modifications must be\n  published under the same license.\n- **Secrets**: The `secrets.peertube` key in `config/*.yaml` must be\n  generated via `openssl rand -hex 32`. Never commit secrets; use\n  `config/local-*.json` overrides (gitignored) or environment variables.\n- **OAuth2**: Access tokens expire in 1 day; refresh tokens in 2 weeks\n  (configurable in `config/default.yaml`).\n- **Rate limiting**: All API endpoints are rate-limited by default\n  (`apiRateLimiter` middleware). Specific limits per category (login,\n  signup, ActivityPub, etc.) are configured in `config/default.yaml`.\n- **CSP**: Content-Security-Policy headers are configurable and applied\n  via `server/core/middlewares/csp.ts`.\n- **Input validation**: Every controller uses express-validator\n  middleware defined in `server/core/middlewares/validators/`.\n- **Vulnerability reporting**: `peertube-security@framasoft.org` —\n  see `SECURITY.md`.\n- **Dependency scanning**: No automated scanner configuration found in\n  the repo.\n\n## Agent Guardrails\n\n### Files and directories agents must NOT modify\n\n- `config/local-*.json` — User-local config overrides (gitignored)\n- `config/production.yaml.example` — Template; changes need release\n  coordination\n- `server/core/initializers/migrations/` — Existing migration files are\n  immutable once released; only append new ones\n- `pnpm-lock.yaml` — Regenerated by `pnpm install`; never edit manually\n- `support/doc/api/openapi.yaml` — Must stay in sync with controllers;\n  validate with `npm run swagger-cli -- validate`\n\n### Required checks before pushing\n\n1. `npm run build:server` must succeed\n2. `npm run lint` must pass\n3. If API surface changed: `npm run swagger-cli -- validate\n   support/doc/api/openapi.yaml`\n4. If database schema changed: create a new migration file **and**\n   increment `LAST_MIGRATION_VERSION` in\n   `server/core/initializers/constants.ts`\n\n### Boundaries\n\n- Do not run `pnpm install` without `--frozen-lockfile`\n- Do not use `npm install` or `yarn` — this project uses **pnpm**\n- Do not add dependencies without explicit approval\n- Do not modify test Docker images or CI service definitions without\n  review\n- Maximum concurrency for background jobs is configured in constants;\n  do not change without benchmarking\n\n## Extensibility Hooks\n\n### Plugin system\n\nPeerTube supports server and client plugins via a hook-based\narchitecture. Plugins register `filter`, `action`, and `static`\nhooks—see `support/doc/plugins/guide.md`.\n\n- Plugin names follow `peertube-plugin-*` (themes: `peertube-theme-*`)\n- Server hooks are registered in `server/core/lib/plugins/`\n- Plugin management API: `/api/v1/plugins`\n- Install/uninstall scripts: `npm run plugin:install`,\n  `npm run plugin:uninstall`\n\n### Configuration\n\nAll runtime configuration is in YAML under `config/`. Local overrides\nuse `config/local-*.json` files (gitignored). Key env vars:\n\n| Variable              | Purpose                              |\n|-----------------------|--------------------------------------|\n| `NODE_ENV`            | `production`, `development`, `test`  |\n| `NODE_CONFIG_DIR`     | Override config directory             |\n| `LOGGER_LEVEL`        | `debug`, `info`, `warn`, `error`     |\n| `PT_INITIAL_ROOT_PASSWORD` | Set root password on first run  |\n\n### Runners (distributed transcoding)\n\nExternal `peertube-runner` processes poll the API for transcoding jobs.\nConfigured in `server/core/lib/runners/` and managed through the\n`/api/v1/runners` endpoints.\n\n### OpenTelemetry\n\nTracing and metrics are instrumented via `@opentelemetry/*` packages.\nExport to an OTLP endpoint like Jaeger (tracing) or Prometheus (metrics) is configurable in\n`config/default.yaml` under the `open_telemetry` key.\n\n## Further Reading\n\n- [support/doc/development/server.md](support/doc/development/server.md)\n  — Server code conventions and new-feature walkthrough\n- [Horizontal scalability](https://docs.joinpeertube.org/maintain/horizontal-scalability)\n  — Running several processes (`--role=secondary`) for one instance\n- [support/doc/development/tests.md](support/doc/development/tests.md)\n  — Test setup and execution guide\n- [support/doc/plugins/guide.md](support/doc/plugins/guide.md)\n  — Plugin & theme development guide\n- [support/doc/api/openapi.yaml](support/doc/api/openapi.yaml)\n  — OpenAPI 3.0 specification\n- [support/doc/production.md](support/doc/production.md)\n  — Production deployment guide\n- [support/doc/docker.md](support/doc/docker.md)\n  — Docker deployment guide\n- [support/doc/development/lib.md](support/doc/development/lib.md)\n  — Library / business-logic documentation\n- [SECURITY.md](SECURITY.md) — Vulnerability disclosure policy\n- [FAQ.md](FAQ.md) — Frequently asked questions\n","isInternal":false,"tokens":3957,"sizeBytes":17129},{"name":"AGENTS.md","path":"client/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/client/AGENTS.md","title":"client - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Client — Angular Frontend SPA\n\nPeerTube's web client is an Angular single-page application served\nunder `/client/`. It communicates with the backend exclusively through\nthe REST API (`/api/v1/`). A separate Vite-built embed player lives\nin `src/standalone/` for third-party iframe embedding.\n\n## Directory Structure\n\n- **src/app/** — Main Angular application\n  - `+about/`, `+admin/`, `+home/`, `+login/`, `+signup/`, etc. —\n    Lazy-loaded route modules (prefixed with `+`)\n  - `core/` — Singleton services: auth, routing, plugins, theme,\n    server config, notifications, screen-size helpers\n  - `shared/` — Reusable components & directives organized by domain\n    (`shared-video/`, `shared-forms/`, `shared-moderation/`, etc.)\n  - `header/`, `menu/`, `modal/` — App shell layout components\n  - `helpers/` — Client-side utility functions\n  - `hotkeys/` — Keyboard shortcut definitions\n  - `app.routes.ts` — Top-level route definitions (lazy-loaded)\n  - `app.component.ts` — Root component\n- **src/root-helpers/** — Framework-agnostic helpers (logger, storage,\n  theme manager, translations, plugin manager) shared between the\n  main app and standalone builds\n- **src/standalone/** — Independently built artifacts:\n  - `player/` — PeerTube video player (Vite build, HLS.js + P2P)\n  - `embed-player-api/` — Public npm package for programmatic\n    embed control (`@peertube/embed-api`)\n  - `videos/` — Embed page (`embed.html`) and test harness\n- **src/sass/** — Global SCSS: Bootstrap overrides, PrimeNG theme,\n  utility classes, z-index scale, fonts\n- **src/locale/** — Angular XLIFF translation files\n- **src/assets/** — Static images and assets\n- **src/environments/** — Angular environment configs\n- **e2e/** — End-to-end tests (WebdriverIO + Mocha)\n- **proxy.config.json** — Dev-server proxy to backend (:9000)\n\n## Build & Development Commands\n\nAll commands run from the **repository root** unless noted.\n\n### Development\n\n```bash\n# Full stack: server (:9000) + Angular dev server (:3000)\nnpm run dev\n\n# Client only (requires a running backend on :9000)\nnpm run dev:client\n\n# Embed player only\nnpm run dev:embed\n```\n\nThe Angular dev server proxies `/api`, `/plugins`, `/themes`,\n`/static`, `/lazy-static`, `/socket.io`, and `/client/assets` to the\nbackend at `http://127.0.0.1:9000` (see `proxy.config.json`).\n\n### Build\n\n```bash\n# Full client build (production)\nnpm run build:client\n\n# Embed player build\nnpm run build:embed\n```\n\nOutput goes to `client/dist/` with per-locale sub-directories\n(e.g. `client/dist/en-US/`, `client/dist/fr-FR/`).\n\n### Lint\n\n```bash\n# From repository root\ncd client\n\n# TypeScript + Angular templates (ESLint)\nnpm run lint-ts\n\n# SCSS (Stylelint)\nnpm run lint-scss\n\n# Both\nnpm run lint\n```\n\n### E2E tests\n\n```bash\n# Local browser (from repo root)\nnpm run e2e:local\n\n# BrowserStack\nnpm run e2e:browserstack\n```\n\nE2E uses **WebdriverIO** with a **Mocha** framework. Config files are\nin `e2e/` (`wdio.local.conf.ts`, `wdio.browserstack.conf.ts`).\n\n## Code Style & Conventions\n\n### TypeScript / ESLint\n\nThe client has its own `eslint.config.mjs` extending\n`eslint-config-love` and `angular-eslint`. Key rules match the\nserver:\n\n| Rule                | Value                             |\n|---------------------|-----------------------------------|\n| Semicolons          | **never** (`@stylistic/semi`)     |\n| Max line length     | 140 characters                    |\n| Array brackets      | Spaces inside `[ 'a', 'b' ]`     |\n| Trailing newline    | Required (`eol-last`)             |\n| Indentation         | 2 spaces                          |\n\n### Angular-specific rules\n\n| Rule                                     | Value                    |\n|------------------------------------------|--------------------------|\n| Component selector prefix               | `my-` (kebab-case)       |\n| Directive selector prefix               | `my` (camelCase)         |\n| View encapsulation                       | Required (enforced)      |\n\n### SCSS / Stylelint\n\nConfigured in `.stylelintrc.json`, extends\n`stylelint-config-sass-guidelines` with `stylelint-order`. Key rules:\n\n- Declaration order: custom properties → declarations → `@include`\n- Max nesting depth: 8\n- Max compound selectors: 9\n- `::ng-deep` pseudo-element allowed\n\n### Naming patterns\n\n- Lazy-loaded route folders: `+feature-name/` (e.g. `+admin/`,\n  `+video-watch/`)\n- Shared modules: `shared-domain/` (e.g. `shared-video/`,\n  `shared-forms/`)\n- Services: PascalCase with `Service` suffix\n  (`AuthService`, `ServerService`)\n- Components: PascalCase with `Component` suffix, selector prefixed\n  `my-` (`my-video-miniature`)\n- Path aliases: `@app/*` → `src/app/*`,\n  `@root-helpers/*` → `src/root-helpers/*`\n\n### Internationalization\n\n- Source locale: `en` (base href `/client/en-US/`)\n- Translation files: XLIFF format in `src/locale/`\n- Merge tool: `@peertube/xliffmerge` (config: `.xliffmerge.json`)\n- Use Angular `$localize` / `i18n` attributes; do NOT use raw strings\n  for user-visible text\n\n## Architecture Notes\n\n```\n┌────────────────────────────────────────────────────────┐\n│                 Angular SPA (client/)                   │\n│                                                         │\n│  ┌──────────┐  ┌──────────────┐  ┌──────────────────┐  │\n│  │  Routes   │  │  Core        │  │  Shared          │  │\n│  │ (+about,  │  │ (auth, REST, │  │ (forms, video    │  │\n│  │  +admin,  │──│  plugins,    │──│  miniature,      │  │\n│  │  +videos) │  │  server,     │  │  moderation...)  │  │\n│  │           │  │  theme)      │  │                  │  │\n│  └──────────┘  └──────┬───────┘  └──────────────────┘  │\n│                        │                                │\n│  ┌─────────────────────▼────────────────────────────┐   │\n│  │           root-helpers (no Angular dep)           │   │\n│  │  logger, storage, plugins-manager, theme, i18n   │   │\n│  └──────────────────────────────────────────────────┘   │\n│                                                         │\n│  ┌─────────────────────────────────────────────────┐    │\n│  │         standalone/ (Vite builds)               │    │\n│  │  player/ │ embed-player-api/ │ videos/embed     │    │\n│  └─────────────────────────────────────────────────┘    │\n└────────────────────────┬────────────────────────────────┘\n                         │ HTTP (REST API)\n                         ▼\n              ┌──────────────────────┐\n              │  Express Backend     │\n              │  (:9000 /api/v1/*)   │\n              └──────────────────────┘\n```\n\n- **Lazy loading**: Each `+feature/` folder exports route configs\n  loaded via `loadChildren` in `app.routes.ts`\n- **Core services**: Singletons bootstrapped in `main.ts` via\n  `getCoreProviders()` — auth, REST client, server config polling,\n  plugin hooks, theme manager\n- **Plugin hooks**: Client-side plugins register via\n  `HooksService` / `PluginService` in `core/plugins/`\n- **State management**: No dedicated store library; services hold\n  state, components subscribe via RxJS observables\n- **UI framework**: Bootstrap 5 + PrimeNG + ng-bootstrap;\n  global SCSS in `src/sass/`\n- **Video player**: Custom build in `standalone/player/` using\n  Video.js + HLS.js + P2P Media Loader; embedded via\n  `standalone/videos/embed.html`\n\n## Agent Guardrails\n\n### Files agents must NOT modify\n\n- `src/locale/*.xlf` — Generated translation files; updated via\n  `npm run i18n:update` only\n- `dist/` — Build output; never edit manually\n- `node_modules/` — Managed by pnpm\n- `.angular/` — Angular build cache\n\n### Required checks before pushing\n\n1. `cd client && npm run lint` must pass (TS + SCSS)\n2. Production build must succeed: `npm run build:client`\n   (from repo root)\n3. If new user-visible strings added: extract with\n   `npm run i18n:create-custom-files` and verify XLIFF\n\n### Boundaries\n\n- Do not import from `server/` — the client communicates with the\n  backend exclusively via the REST API\n- Do not import Angular-specific code in `root-helpers/` or\n  `standalone/` — these must remain framework-agnostic\n- Shared API types come from `@peertube/peertube-models` and\n  `@peertube/peertube-core-utils` (workspace packages)\n- Do not add new npm dependencies without explicit approval\n\n## Further Reading\n\n- [../support/doc/plugins/guide.md](../support/doc/plugins/guide.md)\n  — Plugin & theme development (client hooks)\n- [src/standalone/embed-player-api/README.md](src/standalone/embed-player-api/README.md)\n  — Embed player API documentation\n- [../support/doc/api/embeds.md](../support/doc/api/embeds.md)\n  — Embed integration guide\n- [../AGENTS.md](../AGENTS.md)\n  — Root project AGENTS.md (server, build, CI, testing)\n","isInternal":false,"tokens":2284,"sizeBytes":9813},{"name":"package.json","path":"packages/core-utils/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/core-utils/package.json","title":"@peertube/peertube-core-utils","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@peertube/peertube-core-utils\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","frontmatter":{"name":"@peertube/peertube-core-utils","private":true,"version":"0.0.0","main":"dist/index.js","files":["dist"],"exports":{"types":"./dist/index.d.ts","peertube:tsx":"./src/index.ts","default":"./dist/index.js"},"type":"module","devDependencies":{},"scripts":{"build":"tsc","watch":"tsc -w"},"dependencies":{}},"isInternal":false,"tokens":134,"sizeBytes":391},{"name":"tsconfig.json","path":"packages/core-utils/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/core-utils/tsconfig.json","title":"Core-utils Skill","category":"anthropic-skill","format":"json","content":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../models\" }\n  ]\n}\n","frontmatter":{"extends":"../../tsconfig.base.json","compilerOptions":{"outDir":"./dist","rootDir":"src","tsBuildInfoFile":"./dist/.tsbuildinfo"},"references":[{"path":"../models"}]},"isInternal":false,"tokens":66,"sizeBytes":214},{"name":"package.json","path":"packages/ffmpeg/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/ffmpeg/package.json","title":"@peertube/peertube-ffmpeg","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@peertube/peertube-ffmpeg\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","frontmatter":{"name":"@peertube/peertube-ffmpeg","private":true,"version":"0.0.0","main":"dist/index.js","files":["dist"],"exports":{"types":"./dist/index.d.ts","peertube:tsx":"./src/index.ts","default":"./dist/index.js"},"type":"module","devDependencies":{},"scripts":{"build":"tsc","watch":"tsc -w"},"dependencies":{}},"isInternal":false,"tokens":134,"sizeBytes":387},{"name":"tsconfig.json","path":"packages/ffmpeg/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/ffmpeg/tsconfig.json","title":"Ffmpeg Skill","category":"anthropic-skill","format":"json","content":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../models\" },\n    { \"path\": \"../core-utils\" }\n  ]\n}\n","frontmatter":{"extends":"../../tsconfig.base.json","compilerOptions":{"outDir":"./dist","rootDir":"src","tsBuildInfoFile":"./dist/.tsbuildinfo"},"references":[{"path":"../models"},{"path":"../core-utils"}]},"isInternal":false,"tokens":76,"sizeBytes":247},{"name":"package.json","path":"packages/models/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/models/package.json","title":"@peertube/peertube-models","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@peertube/peertube-models\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"type\": \"module\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","frontmatter":{"name":"@peertube/peertube-models","private":true,"version":"0.0.0","main":"dist/index.js","type":"module","files":["dist"],"exports":{"types":"./dist/index.d.ts","peertube:tsx":"./src/index.ts","default":"./dist/index.js"},"devDependencies":{},"scripts":{"build":"tsc","watch":"tsc -w"},"dependencies":{}},"isInternal":false,"tokens":134,"sizeBytes":387},{"name":"tsconfig.json","path":"packages/models/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/models/tsconfig.json","title":"Models Skill","category":"anthropic-skill","format":"json","content":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  }\n}\n","frontmatter":{"extends":"../../tsconfig.base.json","compilerOptions":{"outDir":"./dist","rootDir":"src","tsBuildInfoFile":"./dist/.tsbuildinfo"}},"isInternal":false,"tokens":50,"sizeBytes":163},{"name":"tsconfig.types.json","path":"packages/models/tsconfig.types.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/models/tsconfig.types.json","title":"Models Skill","category":"anthropic-skill","format":"json","content":"{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../types-generator/dist-tmp/peertube-models\",\n    \"tsBuildInfoFile\": \"../types-generator/dist-tmp/peertube-models/.tsbuildinfo\",\n    \"stripInternal\": true,\n    \"removeComments\": false,\n    \"emitDeclarationOnly\": true\n  }\n}\n","frontmatter":{"extends":"./tsconfig.json","compilerOptions":{"outDir":"../types-generator/dist-tmp/peertube-models","tsBuildInfoFile":"../types-generator/dist-tmp/peertube-models/.tsbuildinfo","stripInternal":true,"removeComments":false,"emitDeclarationOnly":true}},"isInternal":false,"tokens":83,"sizeBytes":295},{"name":"package.json","path":"packages/node-utils/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/node-utils/package.json","title":"@peertube/peertube-node-utils","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@peertube/peertube-node-utils\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n","frontmatter":{"name":"@peertube/peertube-node-utils","private":true,"version":"0.0.0","main":"dist/index.js","files":["dist"],"exports":{"types":"./dist/index.d.ts","peertube:tsx":"./src/index.ts","default":"./dist/index.js"},"type":"module","devDependencies":{},"scripts":{"build":"tsc","watch":"tsc -w"},"dependencies":{}},"isInternal":false,"tokens":134,"sizeBytes":391},{"name":"tsconfig.json","path":"packages/node-utils/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/node-utils/tsconfig.json","title":"Node-utils Skill","category":"anthropic-skill","format":"json","content":"{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../core-utils\" }\n  ]\n}\n","frontmatter":{"extends":"../../tsconfig.base.json","compilerOptions":{"outDir":"./dist","rootDir":"src","tsBuildInfoFile":"./dist/.tsbuildinfo"},"references":[{"path":"../core-utils"}]},"isInternal":false,"tokens":67,"sizeBytes":218},{"name":"package.json","path":"packages/server-commands/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/server-commands/package.json","title":"@peertube/peertube-server-commands","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@peertube/peertube-server-commands\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {\n    \"@aws-sdk/client-s3\": \"^3.1161.0\",\n    \"@types/superagent\": \"^8.1.11\",\n    \"@types/supertest\": \"^7.2.1\",\n    \"supertest\": \"^7.3.1\"\n  },\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {\n    \"@peertube/peertube-core-utils\": \"workspace:*\",\n    \"@peertube/peertube-models\": \"workspace:*\",\n    \"@peertube/peertube-node-utils\": \"workspace:*\",\n    \"@peertube/peertube-typescript-utils\": \"workspace:*\"\n  }\n}\n","frontmatter":{"name":"@peertube/peertube-server-commands","private":true,"version":"0.0.0","main":"dist/index.js","files":["dist"],"exports":{"types":"./dist/index.d.ts","peertube:tsx":"./src/index.ts","default":"./dist/index.js"},"type":"module","devDependencies":{"@aws-sdk/client-s3":"^3.1161.0","@types/superagent":"^8.1.11","@types/supertest":"^7.2.1","supertest":"^7.3.1"},"scripts":{"build":"tsc","watch":"tsc -w"},"dependencies":{"@peertube/peertube-core-utils":"workspace:*","@peertube/peertube-models":"workspace:*","@peertube/peertube-node-utils":"workspace:*","@peertube/peertube-typescript-utils":"workspace:*"}},"isInternal":false,"tokens":262,"sizeBytes":752},{"name":"tsconfig.json","path":"packages/server-commands/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/server-commands/tsconfig.json","title":"Server-commands Skill","category":"anthropic-skill","format":"json","content":"# Server-commands Skill\n\nPath: `packages/server-commands/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/server-commands/tsconfig.json)","tokens":300,"sizeBytes":200},{"name":"bad-body-http-signature.json","path":"packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json","title":"Mastodon Skill","category":"anthropic-skill","format":"json","content":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json)","tokens":300,"sizeBytes":255},{"name":"bad-http-signature.json","path":"packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json","title":"Mastodon Skill","category":"anthropic-skill","format":"json","content":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json)","tokens":300,"sizeBytes":245},{"name":"bad-public-key.json","path":"packages/tests/fixtures/ap-json/mastodon/bad-public-key.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-public-key.json","title":"Mastodon Skill","category":"anthropic-skill","format":"json","content":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-public-key.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-public-key.json)","tokens":300,"sizeBytes":237},{"name":"create-bad-signature.json","path":"packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json","title":"Mastodon Skill","category":"anthropic-skill","format":"json","content":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json)","tokens":300,"sizeBytes":249},{"name":"create.json","path":"packages/tests/fixtures/ap-json/mastodon/create.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create.json","title":"Mastodon Skill","category":"anthropic-skill","format":"json","content":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/create.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create.json)","tokens":300,"sizeBytes":221},{"name":"http-signature.json","path":"packages/tests/fixtures/ap-json/mastodon/http-signature.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/http-signature.json","title":"Mastodon Skill","category":"anthropic-skill","format":"json","content":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/http-signature.json)","tokens":300,"sizeBytes":237},{"name":"public-key.json","path":"packages/tests/fixtures/ap-json/mastodon/public-key.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/public-key.json","title":"Mastodon Skill","category":"anthropic-skill","format":"json","content":"# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/public-key.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/public-key.json)","tokens":300,"sizeBytes":229},{"name":"announce-without-context.json","path":"packages/tests/fixtures/ap-json/peertube/announce-without-context.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/announce-without-context.json","title":"Peertube Skill","category":"anthropic-skill","format":"json","content":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/announce-without-context.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/announce-without-context.json)","tokens":300,"sizeBytes":257},{"name":"invalid-keys.json","path":"packages/tests/fixtures/ap-json/peertube/invalid-keys.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/invalid-keys.json","title":"Peertube Skill","category":"anthropic-skill","format":"json","content":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/invalid-keys.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/invalid-keys.json)","tokens":300,"sizeBytes":233},{"name":"keys.json","path":"packages/tests/fixtures/ap-json/peertube/keys.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/keys.json","title":"Peertube Skill","category":"anthropic-skill","format":"json","content":"# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/keys.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/keys.json)","tokens":300,"sizeBytes":217},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-broken/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-broken/package.json","title":"Peertube-plugin-test-broken Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-broken Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-broken/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-broken/package.json)","tokens":300,"sizeBytes":264},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json","title":"Peertube-plugin-test-css-sourcemap Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-css-sourcemap Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json)","tokens":300,"sizeBytes":285},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json","title":"Peertube-plugin-test-external-auth-four Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-external-auth-four Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json)","tokens":300,"sizeBytes":300},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json","title":"Peertube-plugin-test-external-auth-one Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-external-auth-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json)","tokens":300,"sizeBytes":297},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json","title":"Peertube-plugin-test-external-auth-three Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-external-auth-three Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json)","tokens":300,"sizeBytes":303},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json","title":"Peertube-plugin-test-external-auth-two Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-external-auth-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json)","tokens":300,"sizeBytes":297},{"name":"fr.json","path":"packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json","title":"Languages Skill","category":"anthropic-skill","format":"json","content":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json)","tokens":300,"sizeBytes":282},{"name":"it.json","path":"packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json","title":"Languages Skill","category":"anthropic-skill","format":"json","content":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/it.json)","tokens":300,"sizeBytes":282},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json","title":"Peertube-plugin-test-filter-translations Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-filter-translations Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/package.json)","tokens":300,"sizeBytes":303},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-five/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-five/package.json","title":"Peertube-plugin-test-five Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-five Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-five/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-five/package.json)","tokens":300,"sizeBytes":258},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-four/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-four/package.json","title":"Peertube-plugin-test-four Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-four Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-four/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-four/package.json)","tokens":300,"sizeBytes":258},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json","title":"Peertube-plugin-test-id-pass-auth-one Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-id-pass-auth-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-one/package.json)","tokens":300,"sizeBytes":294},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json","title":"Peertube-plugin-test-id-pass-auth-three Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-id-pass-auth-three Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-three/package.json)","tokens":300,"sizeBytes":300},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json","title":"Peertube-plugin-test-id-pass-auth-two Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-id-pass-auth-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-id-pass-auth-two/package.json)","tokens":300,"sizeBytes":294},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-native/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-native/package.json","title":"Peertube-plugin-test-native Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-native Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-native/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-native/package.json)","tokens":300,"sizeBytes":264},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json","title":"Peertube-plugin-test-podcast-custom-tags Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-podcast-custom-tags Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-podcast-custom-tags/package.json)","tokens":300,"sizeBytes":303},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json","title":"Peertube-plugin-test-secondary-failure Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-secondary-failure Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-secondary-failure/package.json)","tokens":300,"sizeBytes":297},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-secondary/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-secondary/package.json","title":"Peertube-plugin-test-secondary Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-secondary Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-secondary/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-secondary/package.json)","tokens":300,"sizeBytes":273},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-seven/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-seven/package.json","title":"Peertube-plugin-test-seven Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-seven Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-seven/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-seven/package.json)","tokens":300,"sizeBytes":261},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-six/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-six/package.json","title":"Peertube-plugin-test-six Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-six Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-six/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-six/package.json)","tokens":300,"sizeBytes":255},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json","title":"Peertube-plugin-test-slow-live-setup Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-slow-live-setup Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-slow-live-setup/package.json)","tokens":300,"sizeBytes":291},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json","title":"Peertube-plugin-test-transcoding-one Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-transcoding-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcoding-one/package.json)","tokens":300,"sizeBytes":291},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json","title":"Peertube-plugin-test-transcoding-two Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-transcoding-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcoding-two/package.json)","tokens":300,"sizeBytes":291},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-transcription/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcription/package.json","title":"Peertube-plugin-test-transcription Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-transcription Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-transcription/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-transcription/package.json)","tokens":300,"sizeBytes":285},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-unloading/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-unloading/package.json","title":"Peertube-plugin-test-unloading Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-unloading Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-unloading/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-unloading/package.json)","tokens":300,"sizeBytes":273},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-upload-file/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-upload-file/package.json","title":"Peertube-plugin-test-upload-file Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-upload-file Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-upload-file/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-upload-file/package.json)","tokens":300,"sizeBytes":279},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-video-constants/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-video-constants/package.json","title":"Peertube-plugin-test-video-constants Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-video-constants Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-video-constants/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-video-constants/package.json)","tokens":300,"sizeBytes":291},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test-websocket/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-websocket/package.json","title":"Peertube-plugin-test-websocket Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test-websocket Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-websocket/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-websocket/package.json)","tokens":300,"sizeBytes":273},{"name":"fr.json","path":"packages/tests/fixtures/peertube-plugin-test/languages/fr.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test/languages/fr.json","title":"Languages Skill","category":"anthropic-skill","format":"json","content":"# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test/languages/fr.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test/languages/fr.json)","tokens":300,"sizeBytes":242},{"name":"package.json","path":"packages/tests/fixtures/peertube-plugin-test/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test/package.json","title":"Peertube-plugin-test Skill","category":"anthropic-skill","format":"json","content":"# Peertube-plugin-test Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test/package.json)","tokens":300,"sizeBytes":243},{"name":"package.json","path":"packages/tests/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/package.json","title":"Tests Skill","category":"anthropic-skill","format":"json","content":"# Tests Skill\n\nPath: `packages/tests/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/package.json)","tokens":300,"sizeBytes":168},{"name":"tsconfig.json","path":"packages/tests/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/tsconfig.json","title":"Tests Skill","category":"anthropic-skill","format":"json","content":"# Tests Skill\n\nPath: `packages/tests/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/tsconfig.json)","tokens":300,"sizeBytes":170},{"name":"package.json","path":"packages/transcription-devtools/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/package.json","title":"Transcription-devtools Skill","category":"anthropic-skill","format":"json","content":"# Transcription-devtools Skill\n\nPath: `packages/transcription-devtools/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/package.json)","tokens":300,"sizeBytes":219},{"name":"tsconfig.json","path":"packages/transcription-devtools/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/tsconfig.json","title":"Transcription-devtools Skill","category":"anthropic-skill","format":"json","content":"# Transcription-devtools Skill\n\nPath: `packages/transcription-devtools/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/tsconfig.json)","tokens":300,"sizeBytes":221},{"name":"package.json","path":"packages/transcription/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/package.json","title":"Transcription Skill","category":"anthropic-skill","format":"json","content":"# Transcription Skill\n\nPath: `packages/transcription/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/package.json)","tokens":300,"sizeBytes":192},{"name":"tsconfig.json","path":"packages/transcription/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/tsconfig.json","title":"Transcription Skill","category":"anthropic-skill","format":"json","content":"# Transcription Skill\n\nPath: `packages/transcription/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/tsconfig.json)","tokens":300,"sizeBytes":194},{"name":"tsconfig.types.json","path":"packages/transcription/tsconfig.types.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/tsconfig.types.json","title":"Transcription Skill","category":"anthropic-skill","format":"json","content":"# Transcription Skill\n\nPath: `packages/transcription/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/tsconfig.types.json)","tokens":300,"sizeBytes":206},{"name":"package.json","path":"packages/types-generator/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/package.json","title":"Types-generator Skill","category":"anthropic-skill","format":"json","content":"# Types-generator Skill\n\nPath: `packages/types-generator/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/package.json)","tokens":300,"sizeBytes":198},{"name":"tsconfig.types.json","path":"packages/types-generator/src/client/tsconfig.types.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/src/client/tsconfig.types.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `packages/types-generator/src/client/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/src/client/tsconfig.types.json)","tokens":300,"sizeBytes":225},{"name":"tsconfig.dist-tmp.json","path":"packages/types-generator/tsconfig.dist-tmp.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.dist-tmp.json","title":"Types-generator Skill","category":"anthropic-skill","format":"json","content":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.dist-tmp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.dist-tmp.json)","tokens":300,"sizeBytes":218},{"name":"tsconfig.json","path":"packages/types-generator/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.json","title":"Types-generator Skill","category":"anthropic-skill","format":"json","content":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.json)","tokens":300,"sizeBytes":200},{"name":"tsconfig.types.json","path":"packages/types-generator/tsconfig.types.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.types.json","title":"Types-generator Skill","category":"anthropic-skill","format":"json","content":"# Types-generator Skill\n\nPath: `packages/types-generator/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/tsconfig.types.json)","tokens":300,"sizeBytes":212},{"name":"package.json","path":"packages/typescript-utils/package.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/package.json","title":"Typescript-utils Skill","category":"anthropic-skill","format":"json","content":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/package.json)","tokens":300,"sizeBytes":201},{"name":"tsconfig.json","path":"packages/typescript-utils/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/tsconfig.json","title":"Typescript-utils Skill","category":"anthropic-skill","format":"json","content":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/tsconfig.json)","tokens":300,"sizeBytes":203},{"name":"tsconfig.types.json","path":"packages/typescript-utils/tsconfig.types.json","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/tsconfig.types.json","title":"Typescript-utils Skill","category":"anthropic-skill","format":"json","content":"# Typescript-utils Skill\n\nPath: `packages/typescript-utils/tsconfig.types.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/typescript-utils/tsconfig.types.json)","tokens":300,"sizeBytes":215},{"name":"guide.md","path":"support/doc/plugins/guide.md","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/support/doc/plugins/guide.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins Skill\n\nPath: `support/doc/plugins/guide.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/support/doc/plugins/guide.md)","tokens":300,"sizeBytes":172},{"name":"README.md","path":"packages/tests/fixtures/transcription/videos/README.md","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/transcription/videos/README.md","title":"videos Documentation","category":"plugin-manifest","format":"markdown","content":"# videos Documentation\n\nPath: `packages/tests/fixtures/transcription/videos/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/transcription/videos/README.md)","tokens":300,"sizeBytes":231},{"name":"README.md","path":"packages/transcription-devtools/README.md","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/README.md","title":"transcription-devtools Documentation","category":"plugin-manifest","format":"markdown","content":"# transcription-devtools Documentation\n\nPath: `packages/transcription-devtools/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription-devtools/README.md)","tokens":300,"sizeBytes":221},{"name":"README.md","path":"packages/transcription/README.md","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/README.md","title":"transcription Documentation","category":"plugin-manifest","format":"markdown","content":"# transcription Documentation\n\nPath: `packages/transcription/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/transcription/README.md)","tokens":300,"sizeBytes":194},{"name":"README.md","path":"packages/types-generator/README.md","rawUrl":"https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/README.md","title":"types-generator Documentation","category":"plugin-manifest","format":"markdown","content":"# types-generator Documentation\n\nPath: `packages/types-generator/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/types-generator/README.md)","tokens":300,"sizeBytes":200}],"systemPromptSnippet":"<yakaai_skills repo=\"Chocobozzz/PeerTube\">\n<!-- File: AGENTS.md (Tokens: ~3957 | Category: root-instruction) -->\n# Project Overview\n\nPeerTube is an open-source, ActivityPub-federated video streaming platform\nthat uses P2P technology directly in web browsers. Developed by Framasoft\nunder the AGPL-3.0 license, it provides a decentralized alternative to\ncentralized video platforms. The server is a Node.js/Express API with a\nSequelize ORM (PostgreSQL), background job processing (BullMQ/Redis),\nActivityPub federation, and an Angular SPA client. Video transcoding is\nhandled via FFmpeg, with optional distributed runners.\n\n## Repository Structure\n\n- **apps/** — Standalone CLI applications (`peertube-cli`, `peertube-runner`)\n- **client/** — Angular frontend SPA (separate build system)\n- **config/** — YAML configuration files for dev, test, and production\n- **packages/** — Shared workspace packages (monorepo):\n  - `core-utils/` — Shared pure-JS utilities\n  - `ffmpeg/` — FFmpeg wrapper library\n  - `models/` — Shared TypeScript interfaces and API types\n  - `node-utils/` — Node.js-specific helpers\n  - `server-commands/` — HTTP client helpers used by tests\n  - `tests/` — Full test suite (API, CLI, plugins, feeds, etc.)\n  - `transcription/` — Speech-to-text engine integration\n  - `transcription-devtools/` — Transcription benchmarking tools\n  - `types-generator/` — Generates the public `@peertube/peertube-types`\n    package\n  - `typescript-utils/` — Generic TypeScript helpers\n- **scripts/** — Build, CI, dev, release, and i18n shell scripts\n- **server/** — Backend entry point and core application code\n  - `server.ts` — Process entry point\n  - `core/controllers/` — Express route handlers (API, ActivityPub,\n    feeds, tracker)\n  - `core/models/` — Sequelize database models (14 categories)\n  - `core/lib/` — Business logic (transcoding, live, job queue,\n    ActivityPub, plugins, runners, notifications, etc.)\n  - `core/middlewares/` — Auth, rate-limiting, validation, caching, CSP\n  - `core/helpers/` — Utility functions and custom validators\n  - `core/initializers/` — App bootstrap, constants, DB migrations,\n    config loading\n  - `core/types/` — Internal TypeScript type augmentations\n- **support/** — Documentation, Docker, Nginx configs, OpenAPI spec\n\n## Build & Development Commands\n\n### Prerequisites\n\n- Node.js >= 22.x\n- pnpm >= 12 (do **not** use npm or yarn for install)\n- PostgreSQL >= 14 with `pg_trgm` and `unaccent` extensions\n- Redis >= 6.x\n- FFmpeg >= 4.3\n- Python >= 3.8 (for some test tooling)\n\n### Install dependencies\n\n```bash\npnpm install --frozen-lockfile\n```\n\n### Build\n\n```bash\n# Build server only (backend work)\nnpm run build:server\n\n# Build full application (server + client)\nnpm run build\n\n# Build tests\nnpm run build:tests\n\n# Build individual apps\nnpm run build:peertube-cli\nnpm run build:peertube-runner\n```\n\n### Development\n\n```bash\n# Server-only with hot reload (recommended for backend work)\nnpm run dev:server        # http://localhost:9000\n\n# Full stack (server + Angular client)\nnpm run dev               # server :9000, client :3000\n\n# Dev credentials: root / test\n```\n\n### Lint & type-check\n\n```bash\n# Full lint (oxlint + OpenAPI validation)\nnpm run lint\n\n# Oxlint only\nnpm run oxlint\n\n# Validate OpenAPI spec\nnpm run swagger-cli -- validate support/doc/api/openapi.yaml\n\n# TypeScript compilation check\nnpm run tsc -b server/tsconfig.json\n```\n\n### Run in production\n\n```bash\nnpm run start              # server + client\nnpm run start:server       # server only (--no-client)\n```\n\n## Code Style & Conventions\n\n### Formatting (enforced by Oxlint)\n\n| Rule                | Value                                 |\n|---------------------|---------------------------------------|\n| Semicolons          | **never** (`@stylistic/semi`)         |\n| Max line length     | 140 characters                        |\n| Quotes              | Single quotes (TypeScript default)    |\n| Array brackets      | Spaces inside `[ 'a', 'b' ]`         |\n| Trailing newline    | Required (`eol-last`)                 |\n| Indentation         | 2 spaces (TypeScript convention)      |\n\n### Naming patterns\n\n- Database models: `VideoModel`, `UserModel` — PascalCase + `Model` suffix\n- Internal type aliases: `MVideo`, `MVideoWithChannel` — `M` prefix for\n  Sequelize model types with specific association requirements\n- Controllers: one file per resource, registered in parent `index.ts`\n- Validators: mirror controller structure under\n  `server/core/middlewares/validators/`\n\n### Controller pattern\n\n```typescript\nimport express from 'express'\nimport { apiRateLimiter, asyncMiddleware } from '../../middlewares/index.js'\n\nconst router = express.Router()\nrouter.use(apiRateLimiter)  // always include rate limiting\n\nrouter.get('/:id',\n  validationMiddleware,     // always validate inputs\n  asyncMiddleware(handler)  // always wrap async handlers\n)\n```\n\nSecondary processes (`--role=secondary`) serve every route. A route that needs a state only the primary\nprocess has (its file system, data kept in its memory, live sessions, the tracker...) must start with the\n`primaryOnly` middleware, before any side effect: a secondary answers `421` and nginx replays the request on\nthe primary. Requests whose body nginx streams (`proxy_request_buffering off` locations) cannot be replayed:\nroute them to `backend` in the `$peertube_pool` map of `support/nginx/peertube`.\n\n### Commit messages\n\nNo formal commit-message template.\n\n### Oxlint config\n\nDefined in `oxlint.config.mjs`. Applies to `server/**/*.ts`,\n`scripts/**/*.ts`, `packages/**/*.ts`, `apps/**/*.ts`. The `client/`\ndirectory has its own lint config.\n\n## Architecture Notes\n\n```\n                  ┌──────────────────────────────────────────┐\n                  │            Reverse Proxy (Nginx)         │\n                  └──────────────┬───────────────────────────┘\n                                 │\n              ┌──────────────────▼──────────────────────┐\n              │          Express.js API Server           │\n              │  (server/server.ts → core/controllers/)  │\n              │                                          │\n              │  ┌─────────┐ ┌──────────┐ ┌──────────┐  │\n              │  │  REST   │ │Activity- │ │  Feeds/  │  │\n              │  │  API    │ │  Pub     │ │  oEmbed  │  │\n              │  │  /api/* │ │  /inbox  │ │  /feeds  │  │\n              │  └────┬────┘ └────┬─────┘ └────┬─────┘  │\n              │       │           │             │        │\n              │  ┌────▼───────────▼─────────────▼────┐  │\n              │  │       Middleware Pipeline          │  │\n              │  │  (auth, validators, rate-limit)    │  │\n              │  └────────────────┬───────────────────┘  │\n              │                   │                      │\n              │  ┌────────────────▼───────────────────┐  │\n              │  │        Business Logic (lib/)       │  │\n              │  │  videos, live, transcoding,        │  │\n              │  │  federation, notifications,        │  │\n              │  │  plugins, runners                  │  │\n              │  └──┬──────────┬──────────────┬───┘   │\n              └─────┼──────────┼──────────────┼───────┘\n                    │          │              │\n          ┌────────▼──┐ ┌─────▼─────┐ ┌──────▼──────┐\n          │PostgreSQL │ │   Redis   │ │  FFmpeg /   │\n          │(Sequelize)│ │ (BullMQ   │ │  Runners    │\n          │           │ │  + cache) │ │             │\n          └───────────┘ └───────────┘ └─────────────┘\n```\n\n**Startup sequence** (`server/server.ts`):\n\n1. Register OpenTelemetry tracing\n2. Pre-init checks (config, FFmpeg, Node.js version)\n3. Connect to PostgreSQL, run migrations\n4. Initialize Sequelize models and load i18n\n5. Configure Express middleware stack (proxy trust, CSP, CORS,\n   rate-limiting, OAuth2 auth, express-validator)\n6. Mount route controllers and start listening\n\n**Key data flows**:\n\n- **Video upload**: REST API → validator middleware → `lib/video.ts` →\n  job queue → FFmpeg transcoding → HLS/web-video files → object\n  storage or local filesystem\n- **Federation**: Incoming ActivityPub requests → signature\n  verification → `lib/activitypub/` processors → local DB updates +\n  outgoing fan-out\n- **Live streaming**: RTMP ingest → FFmpeg segmenter → HLS manifest →\n  P2P delivery via WebSocket tracker\n\n## Testing Strategy\n\n### Test framework\n\n- **Mocha** for all server/API tests\n- **GNU Parallel** for running test files concurrently in CI\n- Tests live in `packages/tests/src/` (TypeScript source) and are\n  compiled to `packages/tests/dist/`\n\n### Preparation\n\n```bash\n# Create PostgreSQL superuser for test DB management\nsudo -u postgres createuser $(whoami) --createdb --superuser\n\n# Clean test databases\nnpm run clean:server:test\n\n# Build server + tests\nnpm run build:server\nnpm run build:tests\n```\n\n### Running tests\n\n```bash\n# Full suite (slow, ~45-60 min)\nnpm run test\n\n# Run a specific CI suite\nnpm run ci -- api-check-params-search       # check-params, search\nnpm run ci -- api-videos-1 | api-videos-2   # videos, split in 2 shards balanced by duration\nnpm run ci -- api-server                    # server\nnpm run ci -- api-live-scalability          # live, horizontal-scalability\nnpm run ci -- api-users-stats               # users, stats\nnpm run ci -- api-moderation-notifications  # moderation, notifications\nnpm run ci -- api-federation                # activitypub, redundancy\nnpm run ci -- api-object-storage            # object-storage\nnpm run ci -- api-transcoding-1 | api-transcoding-2  # transcoding + runners, split in 2 shards\nnpm run ci -- client      # feeds, client, misc-endpoints, plugins\nnpm run ci -- cli-plugin  # CLI and plugin tests\nnpm run ci -- lint        # OXlint + OpenAPI validation + client lint\nnpm run ci -- transcription\nnpm run ci -- external-plugins\n\n# Run a single test file\nnpm run mocha -- --timeout 30000 --exit --bail \\\n  packages/tests/src/api/videos/single-server.ts\n```\n\n### External test dependencies (Docker)\n\nSome tests require these containers:\n\n```bash\ndocker run -p 9444:8000 -e S3BACKEND=mem -e REMOTE_MANAGEMENT_DISABLE=1 \\\n  -e SCALITY_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \\\n  -e SCALITY_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \\\n  ghcr.io/scality/cloudserver:9.3.20\ndocker run -p 10389:10389 chocobozzz/docker-test-openldap\ndocker run -p 8082:8080 \\\n  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \\\n  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \\\n  chocobozzz/peertube-tests-keycloak\n```\n\n### CI pipeline\n\nGitHub Actions (`.github/workflows/test.yml`), Ubuntu 22.04, Node.js\n22.x. Matrix strategy runs suites in parallel: `types-package`,\n`client`, the `api-*` suites listed above, `cli-plugin`, `lint`, `transcription`,\n`external-plugins`.\n\nServices provisioned per job: PostgreSQL 10, Redis, LDAP, S3 Ninja,\nKeycloak.\n\n### Environment variables for tests\n\n| Variable                                   | Purpose                     |\n|--------------------------------------------|-----------------------------|\n| `DISABLE_HTTP_IMPORT_TESTS=true`           | Skip flaky HTTP import tests|\n| `DISABLE_HTTP_YOUTUBE_IMPORT_TESTS=true`   | Skip YouTube import tests   |\n| `ENABLE_OBJECT_STORAGE_TESTS=true`         | Enable S3 tests             |\n\n## Security & Compliance\n\n- **License**: AGPL-3.0 — all network-facing modifications must be\n  published under the same license.\n- **Secrets**: The `secrets.peertube` key in `config/*.yaml` must be\n  generated via `openssl rand -hex 32`. Never commit secrets; use\n  `config/local-*.json` overrides (gitignored) or environment variables.\n- **OAuth2**: Access tokens expire in 1 day; refresh tokens in 2 weeks\n  (configurable in `config/default.yaml`).\n- **Rate limiting**: All API endpoints are rate-limited by default\n  (`apiRateLimiter` middleware). Specific limits per category (login,\n  signup, ActivityPub, etc.) are configured in `config/default.yaml`.\n- **CSP**: Content-Security-Policy headers are configurable and applied\n  via `server/core/middlewares/csp.ts`.\n- **Input validation**: Every controller uses express-validator\n  middleware defined in `server/core/middlewares/validators/`.\n- **Vulnerability reporting**: `peertube-security@framasoft.org` —\n  see `SECURITY.md`.\n- **Dependency scanning**: No automated scanner configuration found in\n  the repo.\n\n## Agent Guardrails\n\n### Files and directories agents must NOT modify\n\n- `config/local-*.json` — User-local config overrides (gitignored)\n- `config/production.yaml.example` — Template; changes need release\n  coordination\n- `server/core/initializers/migrations/` — Existing migration files are\n  immutable once released; only append new ones\n- `pnpm-lock.yaml` — Regenerated by `pnpm install`; never edit manually\n- `support/doc/api/openapi.yaml` — Must stay in sync with controllers;\n  validate with `npm run swagger-cli -- validate`\n\n### Required checks before pushing\n\n1. `npm run build:server` must succeed\n2. `npm run lint` must pass\n3. If API surface changed: `npm run swagger-cli -- validate\n   support/doc/api/openapi.yaml`\n4. If database schema changed: create a new migration file **and**\n   increment `LAST_MIGRATION_VERSION` in\n   `server/core/initializers/constants.ts`\n\n### Boundaries\n\n- Do not run `pnpm install` without `--frozen-lockfile`\n- Do not use `npm install` or `yarn` — this project uses **pnpm**\n- Do not add dependencies without explicit approval\n- Do not modify test Docker images or CI service definitions without\n  review\n- Maximum concurrency for background jobs is configured in constants;\n  do not change without benchmarking\n\n## Extensibility Hooks\n\n### Plugin system\n\nPeerTube supports server and client plugins via a hook-based\narchitecture. Plugins register `filter`, `action`, and `static`\nhooks—see `support/doc/plugins/guide.md`.\n\n- Plugin names follow `peertube-plugin-*` (themes: `peertube-theme-*`)\n- Server hooks are registered in `server/core/lib/plugins/`\n- Plugin management API: `/api/v1/plugins`\n- Install/uninstall scripts: `npm run plugin:install`,\n  `npm run plugin:uninstall`\n\n### Configuration\n\nAll runtime configuration is in YAML under `config/`. Local overrides\nuse `config/local-*.json` files (gitignored). Key env vars:\n\n| Variable              | Purpose                              |\n|-----------------------|--------------------------------------|\n| `NODE_ENV`            | `production`, `development`, `test`  |\n| `NODE_CONFIG_DIR`     | Override config directory             |\n| `LOGGER_LEVEL`        | `debug`, `info`, `warn`, `error`     |\n| `PT_INITIAL_ROOT_PASSWORD` | Set root password on first run  |\n\n### Runners (distributed transcoding)\n\nExternal `peertube-runner` processes poll the API for transcoding jobs.\nConfigured in `server/core/lib/runners/` and managed through the\n`/api/v1/runners` endpoints.\n\n### OpenTelemetry\n\nTracing and metrics are instrumented via `@opentelemetry/*` packages.\nExport to an OTLP endpoint like Jaeger (tracing) or Prometheus (metrics) is configurable in\n`config/default.yaml` under the `open_telemetry` key.\n\n## Further Reading\n\n- [support/doc/development/server.md](support/doc/development/server.md)\n  — Server code conventions and new-feature walkthrough\n- [Horizontal scalability](https://docs.joinpeertube.org/maintain/horizontal-scalability)\n  — Running several processes (`--role=secondary`) for one instance\n- [support/doc/development/tests.md](support/doc/development/tests.md)\n  — Test setup and execution guide\n- [support/doc/plugins/guide.md](support/doc/plugins/guide.md)\n  — Plugin & theme development guide\n- [support/doc/api/openapi.yaml](support/doc/api/openapi.yaml)\n  — OpenAPI 3.0 specification\n- [support/doc/production.md](support/doc/production.md)\n  — Production deployment guide\n- [support/doc/docker.md](support/doc/docker.md)\n  — Docker deployment guide\n- [support/doc/development/lib.md](support/doc/development/lib.md)\n  — Library / business-logic documentation\n- [SECURITY.md](SECURITY.md) — Vulnerability disclosure policy\n- [FAQ.md](FAQ.md) — Frequently asked questions\n\n<!-- File: client/AGENTS.md (Tokens: ~2284 | Category: root-instruction) -->\n# Client — Angular Frontend SPA\n\nPeerTube's web client is an Angular single-page application served\nunder `/client/`. It communicates with the backend exclusively through\nthe REST API (`/api/v1/`). A separate Vite-built embed player lives\nin `src/standalone/` for third-party iframe embedding.\n\n## Directory Structure\n\n- **src/app/** — Main Angular application\n  - `+about/`, `+admin/`, `+home/`, `+login/`, `+signup/`, etc. —\n    Lazy-loaded route modules (prefixed with `+`)\n  - `core/` — Singleton services: auth, routing, plugins, theme,\n    server config, notifications, screen-size helpers\n  - `shared/` — Reusable components & directives organized by domain\n    (`shared-video/`, `shared-forms/`, `shared-moderation/`, etc.)\n  - `header/`, `menu/`, `modal/` — App shell layout components\n  - `helpers/` — Client-side utility functions\n  - `hotkeys/` — Keyboard shortcut definitions\n  - `app.routes.ts` — Top-level route definitions (lazy-loaded)\n  - `app.component.ts` — Root component\n- **src/root-helpers/** — Framework-agnostic helpers (logger, storage,\n  theme manager, translations, plugin manager) shared between the\n  main app and standalone builds\n- **src/standalone/** — Independently built artifacts:\n  - `player/` — PeerTube video player (Vite build, HLS.js + P2P)\n  - `embed-player-api/` — Public npm package for programmatic\n    embed control (`@peertube/embed-api`)\n  - `videos/` — Embed page (`embed.html`) and test harness\n- **src/sass/** — Global SCSS: Bootstrap overrides, PrimeNG theme,\n  utility classes, z-index scale, fonts\n- **src/locale/** — Angular XLIFF translation files\n- **src/assets/** — Static images and assets\n- **src/environments/** — Angular environment configs\n- **e2e/** — End-to-end tests (WebdriverIO + Mocha)\n- **proxy.config.json** — Dev-server proxy to backend (:9000)\n\n## Build & Development Commands\n\nAll commands run from the **repository root** unless noted.\n\n### Development\n\n```bash\n# Full stack: server (:9000) + Angular dev server (:3000)\nnpm run dev\n\n# Client only (requires a running backend on :9000)\nnpm run dev:client\n\n# Embed player only\nnpm run dev:embed\n```\n\nThe Angular dev server proxies `/api`, `/plugins`, `/themes`,\n`/static`, `/lazy-static`, `/socket.io`, and `/client/assets` to the\nbackend at `http://127.0.0.1:9000` (see `proxy.config.json`).\n\n### Build\n\n```bash\n# Full client build (production)\nnpm run build:client\n\n# Embed player build\nnpm run build:embed\n```\n\nOutput goes to `client/dist/` with per-locale sub-directories\n(e.g. `client/dist/en-US/`, `client/dist/fr-FR/`).\n\n### Lint\n\n```bash\n# From repository root\ncd client\n\n# TypeScript + Angular templates (ESLint)\nnpm run lint-ts\n\n# SCSS (Stylelint)\nnpm run lint-scss\n\n# Both\nnpm run lint\n```\n\n### E2E tests\n\n```bash\n# Local browser (from repo root)\nnpm run e2e:local\n\n# BrowserStack\nnpm run e2e:browserstack\n```\n\nE2E uses **WebdriverIO** with a **Mocha** framework. Config files are\nin `e2e/` (`wdio.local.conf.ts`, `wdio.browserstack.conf.ts`).\n\n## Code Style & Conventions\n\n### TypeScript / ESLint\n\nThe client has its own `eslint.config.mjs` extending\n`eslint-config-love` and `angular-eslint`. Key rules match the\nserver:\n\n| Rule                | Value                             |\n|---------------------|-----------------------------------|\n| Semicolons          | **never** (`@stylistic/semi`)     |\n| Max line length     | 140 characters                    |\n| Array brackets      | Spaces inside `[ 'a', 'b' ]`     |\n| Trailing newline    | Required (`eol-last`)             |\n| Indentation         | 2 spaces                          |\n\n### Angular-specific rules\n\n| Rule                                     | Value                    |\n|------------------------------------------|--------------------------|\n| Component selector prefix               | `my-` (kebab-case)       |\n| Directive selector prefix               | `my` (camelCase)         |\n| View encapsulation                       | Required (enforced)      |\n\n### SCSS / Stylelint\n\nConfigured in `.stylelintrc.json`, extends\n`stylelint-config-sass-guidelines` with `stylelint-order`. Key rules:\n\n- Declaration order: custom properties → declarations → `@include`\n- Max nesting depth: 8\n- Max compound selectors: 9\n- `::ng-deep` pseudo-element allowed\n\n### Naming patterns\n\n- Lazy-loaded route folders: `+feature-name/` (e.g. `+admin/`,\n  `+video-watch/`)\n- Shared modules: `shared-domain/` (e.g. `shared-video/`,\n  `shared-forms/`)\n- Services: PascalCase with `Service` suffix\n  (`AuthService`, `ServerService`)\n- Components: PascalCase with `Component` suffix, selector prefixed\n  `my-` (`my-video-miniature`)\n- Path aliases: `@app/*` → `src/app/*`,\n  `@root-helpers/*` → `src/root-helpers/*`\n\n### Internationalization\n\n- Source locale: `en` (base href `/client/en-US/`)\n- Translation files: XLIFF format in `src/locale/`\n- Merge tool: `@peertube/xliffmerge` (config: `.xliffmerge.json`)\n- Use Angular `$localize` / `i18n` attributes; do NOT use raw strings\n  for user-visible text\n\n## Architecture Notes\n\n```\n┌────────────────────────────────────────────────────────┐\n│                 Angular SPA (client/)                   │\n│                                                         │\n│  ┌──────────┐  ┌──────────────┐  ┌──────────────────┐  │\n│  │  Routes   │  │  Core        │  │  Shared          │  │\n│  │ (+about,  │  │ (auth, REST, │  │ (forms, video    │  │\n│  │  +admin,  │──│  plugins,    │──│  miniature,      │  │\n│  │  +videos) │  │  server,     │  │  moderation...)  │  │\n│  │           │  │  theme)      │  │                  │  │\n│  └──────────┘  └──────┬───────┘  └──────────────────┘  │\n│                        │                                │\n│  ┌─────────────────────▼────────────────────────────┐   │\n│  │           root-helpers (no Angular dep)           │   │\n│  │  logger, storage, plugins-manager, theme, i18n   │   │\n│  └──────────────────────────────────────────────────┘   │\n│                                                         │\n│  ┌─────────────────────────────────────────────────┐    │\n│  │         standalone/ (Vite builds)               │    │\n│  │  player/ │ embed-player-api/ │ videos/embed     │    │\n│  └─────────────────────────────────────────────────┘    │\n└────────────────────────┬────────────────────────────────┘\n                         │ HTTP (REST API)\n                         ▼\n              ┌──────────────────────┐\n              │  Express Backend     │\n              │  (:9000 /api/v1/*)   │\n              └──────────────────────┘\n```\n\n- **Lazy loading**: Each `+feature/` folder exports route configs\n  loaded via `loadChildren` in `app.routes.ts`\n- **Core services**: Singletons bootstrapped in `main.ts` via\n  `getCoreProviders()` — auth, REST client, server config polling,\n  plugin hooks, theme manager\n- **Plugin hooks**: Client-side plugins register via\n  `HooksService` / `PluginService` in `core/plugins/`\n- **State management**: No dedicated store library; services hold\n  state, components subscribe via RxJS observables\n- **UI framework**: Bootstrap 5 + PrimeNG + ng-bootstrap;\n  global SCSS in `src/sass/`\n- **Video player**: Custom build in `standalone/player/` using\n  Video.js + HLS.js + P2P Media Loader; embedded via\n  `standalone/videos/embed.html`\n\n## Agent Guardrails\n\n### Files agents must NOT modify\n\n- `src/locale/*.xlf` — Generated translation files; updated via\n  `npm run i18n:update` only\n- `dist/` — Build output; never edit manually\n- `node_modules/` — Managed by pnpm\n- `.angular/` — Angular build cache\n\n### Required checks before pushing\n\n1. `cd client && npm run lint` must pass (TS + SCSS)\n2. Production build must succeed: `npm run build:client`\n   (from repo root)\n3. If new user-visible strings added: extract with\n   `npm run i18n:create-custom-files` and verify XLIFF\n\n### Boundaries\n\n- Do not import from `server/` — the client communicates with the\n  backend exclusively via the REST API\n- Do not import Angular-specific code in `root-helpers/` or\n  `standalone/` — these must remain framework-agnostic\n- Shared API types come from `@peertube/peertube-models` and\n  `@peertube/peertube-core-utils` (workspace packages)\n- Do not add new npm dependencies without explicit approval\n\n## Further Reading\n\n- [../support/doc/plugins/guide.md](../support/doc/plugins/guide.md)\n  — Plugin & theme development (client hooks)\n- [src/standalone/embed-player-api/README.md](src/standalone/embed-player-api/README.md)\n  — Embed player API documentation\n- [../support/doc/api/embeds.md](../support/doc/api/embeds.md)\n  — Embed integration guide\n- [../AGENTS.md](../AGENTS.md)\n  — Root project AGENTS.md (server, build, CI, testing)\n\n<!-- File: packages/core-utils/package.json (Tokens: ~134 | Category: anthropic-skill) -->\n{\n  \"name\": \"@peertube/peertube-core-utils\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n\n<!-- File: packages/core-utils/tsconfig.json (Tokens: ~66 | Category: anthropic-skill) -->\n{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../models\" }\n  ]\n}\n\n<!-- File: packages/ffmpeg/package.json (Tokens: ~134 | Category: anthropic-skill) -->\n{\n  \"name\": \"@peertube/peertube-ffmpeg\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n\n<!-- File: packages/ffmpeg/tsconfig.json (Tokens: ~76 | Category: anthropic-skill) -->\n{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../models\" },\n    { \"path\": \"../core-utils\" }\n  ]\n}\n\n<!-- File: packages/models/package.json (Tokens: ~134 | Category: anthropic-skill) -->\n{\n  \"name\": \"@peertube/peertube-models\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"type\": \"module\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n\n<!-- File: packages/models/tsconfig.json (Tokens: ~50 | Category: anthropic-skill) -->\n{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  }\n}\n\n<!-- File: packages/models/tsconfig.types.json (Tokens: ~83 | Category: anthropic-skill) -->\n{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../types-generator/dist-tmp/peertube-models\",\n    \"tsBuildInfoFile\": \"../types-generator/dist-tmp/peertube-models/.tsbuildinfo\",\n    \"stripInternal\": true,\n    \"removeComments\": false,\n    \"emitDeclarationOnly\": true\n  }\n}\n\n<!-- File: packages/node-utils/package.json (Tokens: ~134 | Category: anthropic-skill) -->\n{\n  \"name\": \"@peertube/peertube-node-utils\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [ \"dist\" ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {},\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {}\n}\n\n<!-- File: packages/node-utils/tsconfig.json (Tokens: ~67 | Category: anthropic-skill) -->\n{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"src\",\n    \"tsBuildInfoFile\": \"./dist/.tsbuildinfo\"\n  },\n  \"references\": [\n    { \"path\": \"../core-utils\" }\n  ]\n}\n\n<!-- File: packages/server-commands/package.json (Tokens: ~262 | Category: anthropic-skill) -->\n{\n  \"name\": \"@peertube/peertube-server-commands\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"dist/index.js\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"exports\": {\n    \"types\": \"./dist/index.d.ts\",\n    \"peertube:tsx\": \"./src/index.ts\",\n    \"default\": \"./dist/index.js\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {\n    \"@aws-sdk/client-s3\": \"^3.1161.0\",\n    \"@types/superagent\": \"^8.1.11\",\n    \"@types/supertest\": \"^7.2.1\",\n    \"supertest\": \"^7.3.1\"\n  },\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch\": \"tsc -w\"\n  },\n  \"dependencies\": {\n    \"@peertube/peertube-core-utils\": \"workspace:*\",\n    \"@peertube/peertube-models\": \"workspace:*\",\n    \"@peertube/peertube-node-utils\": \"workspace:*\",\n    \"@peertube/peertube-typescript-utils\": \"workspace:*\"\n  }\n}\n\n<!-- File: packages/server-commands/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Server-commands Skill\n\nPath: `packages/server-commands/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/server-commands/tsconfig.json)\n\n<!-- File: packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-body-http-signature.json)\n\n<!-- File: packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-http-signature.json)\n\n<!-- File: packages/tests/fixtures/ap-json/mastodon/bad-public-key.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/bad-public-key.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/bad-public-key.json)\n\n<!-- File: packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create-bad-signature.json)\n\n<!-- File: packages/tests/fixtures/ap-json/mastodon/create.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/create.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/create.json)\n\n<!-- File: packages/tests/fixtures/ap-json/mastodon/http-signature.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/http-signature.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/http-signature.json)\n\n<!-- File: packages/tests/fixtures/ap-json/mastodon/public-key.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Mastodon Skill\n\nPath: `packages/tests/fixtures/ap-json/mastodon/public-key.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/mastodon/public-key.json)\n\n<!-- File: packages/tests/fixtures/ap-json/peertube/announce-without-context.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/announce-without-context.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/announce-without-context.json)\n\n<!-- File: packages/tests/fixtures/ap-json/peertube/invalid-keys.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/invalid-keys.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/invalid-keys.json)\n\n<!-- File: packages/tests/fixtures/ap-json/peertube/keys.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube Skill\n\nPath: `packages/tests/fixtures/ap-json/peertube/keys.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/ap-json/peertube/keys.json)\n\n<!-- File: packages/tests/fixtures/peertube-plugin-test-broken/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube-plugin-test-broken Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-broken/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-broken/package.json)\n\n<!-- File: packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube-plugin-test-css-sourcemap Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-css-sourcemap/package.json)\n\n<!-- File: packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube-plugin-test-external-auth-four Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-four/package.json)\n\n<!-- File: packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube-plugin-test-external-auth-one Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-one/package.json)\n\n<!-- File: packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube-plugin-test-external-auth-three Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-three/package.json)\n\n<!-- File: packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Peertube-plugin-test-external-auth-two Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-external-auth-two/package.json)\n\n<!-- File: packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Languages Skill\n\nPath: `packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/Chocobozzz/PeerTube/HEAD/packages/tests/fixtures/peertube-plugin-test-filter-translations/languages/fr.json)\n\n<!-- ... +43 more modular skills available via /api/skills/Chocobozzz/PeerTube?path={path} -->\n</yakaai_skills>"}