MyGo 云音乐
Go와 MyGo로 만든 서드파티 네이버 클라우드 뮤직 데스크톱 클라이언트
MovieClaw: 차세대 AI 미디어 서버
MovieClaw is a next-gen AI media server. A single container replaces Sonarr, Radarr, Prowlarr, Bazarr, Jellyseerr, and Jellyfin. It comes with a web app, a native iOS app, and a built-in AI agent that
미디어Python · SwiftGitHub @movieclaw온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
Next-gen AI media server. One container replaces Sonarr, Radarr, Prowlarr, Bazarr, Jellyseerr and Jellyfin, with a web app, a native iPhone app, and an AI agent that gets things done. Free for personal use.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
One server replaces your entire media stack.
A web app and a native iPhone app included, with an AI agent that actually gets things done.
Everything stays on your own hardware. Free for personal and household use.
Want to look around first? Open the live demo : the sign-in page lists four demo accounts, one click each.
It's read-only and resets every day. (The interface and logs are currently in Chinese.)
One install. That's all you need.README 전문 보기 ↗It used to take six or seven services, six or seven configs, and a lot of effort to keep them all agreeing about the same library. Now it's just MovieClaw:
| The job | The usual stack | MovieClaw |
|---|---|---|
| Playback, poster wall, watch progress | Jellyfin / Emby / Plex | Built in |
| Disc rips and 4K HDR on an iPhone | A third-party player like Infuse | A native app of its own, and Infuse still connects |
| Metadata | Whatever the server ships, plus tinyMediaManager for the hard cases | Built in, with TMDB and Douban as dual sources |
| Subscriptions and automatic downloads | Sonarr + Radarr | Built in |
| Indexers and tracker sites | Prowlarr / Jackett | Built in |
| Subtitles | Bazarr | Built in, with PGS-to-SRT conversion and AI translation when none exist |
| Family requests and permissions | Overseerr / Jellyseerr | Built-in member management |
| Running all of the above from a single sentence | Nothing does this | Built-in AI agent, and outside agents can plug in too |
| Total | 6 containers, 6 configs | 1 container, 1 data directory |
All-in-one has its trade-offs, and they're laid out honestly in Boundaries.
Watch right in your browser, or in native apps on your phone, TV, and Mac. iPhone, Apple TV, and Mac share one playback engine of its own: FFmpeg unpacks, Apple plays.
Getting the apps: apps for iPhone, Android, Apple TV, Android TV, and Mac are all on the
download page, with versions, system requirements, and
install steps for each. The iPhone app is on its way to the App Store. Until then, download
MovieClaw-iOS-unsigned.ipa from Releases
and sideload it with AltStore, SideStore, or Sideloadly using your own Apple ID (iOS 26 or
later; sideloaded builds can't receive push notifications). Trackers and download clients are
configured in the web app.
Want an email when a new app launches or a new version ships? Get updates on the website. Sign in, pick an email address, and unsubscribe anytime.
The web app is liquid glass: the sidebar, inputs, and floating buttons refract whatever background image you choose, with a touch of chromatic aberration at the edges. Swap the background under Settings → Appearance, and it stays consistent on every device connected to the same instance.
Windows client development is available in apps/desktop, using Tauri/WebView2 and bundled mpv. See its build, packaging and validation requirements before distributing a Windows build.
MovieClaw puts an autonomous, general-purpose AI agent inside your media server. Organizing your library, making subtitles, handling all those quirky one-off requests: all you have to do is ask.
You can talk to it from WeChat too, by text or voice; Telegram and Discord work as well, and Feishu groups can join as a push-only outlet. It checks with you before deleting anything, and every tool it calls is right there for you to see. The rules are spelled out under Boundaries.
The agent needs an LLM connected under Settings → Model Providers (any OpenAI-compatible
endpoint). Skip it and everything else still works. Teach it "skills" in plain Markdown:
drop a directory with a SKILL.md into data/agent-skills/ (a description in the
frontmatter, instructions in the body, scripts welcome) and the agent loads it on its own
whenever a web-session task matches. Changes take effect immediately, no restart. A skill
sharing a name with a built-in one overrides it (the log says so). Details in
docs/design/agent-skills.md.
Release names aren't guessed at with regexes. A small NER model, distilled from a large language model, parses one in about 3 ms on a plain CPU, and resolution, source, codec, subtitles, audio, and release group each get their own field:
三体.Three-Body.2023.S01E05.2160p.WEB-DL.H265.AAC.国语中字-OurTV
↓
Series · Season 1 Episode 5 · 2160p · H.265 · WEB-DL · AAC
Subtitles: Chinese Audio: Mandarin Release group: OurTV
Even shorthand like "国语中字" (Mandarin audio, Chinese subs), which only exists on Chinese trackers, splits cleanly into separate subtitle and audio fields. When it isn't sure, it doesn't guess: ambiguous items land in a pending identification queue with a plain-language reason ("3 equally plausible matches; not choosing for you"), and one confirmation resolves the whole group.
Every feature is available through the mclaw CLI and MCP. Connect ChatGPT, Claude,
WorkBuddy, Cursor, or Claude Code, and they can subscribe, run quality upgrades, and
organize your library: anything you can do in the web app. The command tree is generated
straight from the server's API, so ship a feature on the backend and every agent can use it.
Subscribe to a show, and everything after that (search, download, identify, fetch metadata, import, notify) runs on its own. No more keeping settings in sync across a handful of services.
Screenshots are from the public live demo, featuring open movies released by the Blender Foundation and others (CC BY).
.mcplugin by hand.example/GUIDE.md, or ask the AI assistant to write it for you.data/ directory. Back that up, delete the container: nothing is lost.A media library, a file organizer, and an assistant that can execute commands, all in one product — the risk is real. The self-hosting community already has horror stories of auto-organizers wiping libraries: "everything deleted, not one source file left." So the constraints here are enforced in code, not politely requested in a prompt:
bash subprocess.rm. Copies that are still seeding are left alone.Got one of these? You're good to go:
One prerequisite: Docker (Synology's built-in Container Manager counts; other NAS brands
have their own Docker packages). The official image
movieclaw/movieclaw runs everything in
a single container — no separate database, no Redis, and a TMDB key is already baked in,
so there's nothing to apply for. One tag covers both x86_64 and ARM64.
Step 1: Create a new folder, create a docker-compose.yml inside it, and paste:
services:
movieclaw:
image: movieclaw/movieclaw:latest
container_name: movieclaw
init: true
ports:
# Left side is the host port — if it's taken, change the left side
# (e.g. "8096:3000") and keep the right side at 3000
- "3000:3000"
# LAN auto-discovery: MovieClaw's apps and Jellyfin players use it to
# find the server. Comment it out if Jellyfin / Emby already runs on this
# host — the port clash would stop the container from starting
- "7359:7359/udp"
volumes:
- ./data:/app/data # Runtime data — backing up this folder is all you need
# (includes the hidden file .secret_key; make sure your
# backup tool doesn't skip dotfiles)
- /volume1/media:/media # ← change to your media directory
- /volume1/downloads:/downloads # ← change to your download client's save directory
# Multiple media disks / download directories? Add one line each — no limit:
# - /volume2/movies:/movies
environment:
- TZ=Asia/Shanghai # ← change to your timezone
# For NVIDIA hardware transcoding, enable these two together with
# `runtime: nvidia` below:
# - NVIDIA_VISIBLE_DEVICES=all
# - NVIDIA_DRIVER_CAPABILITIES=all
# Want hardware transcoding with an Intel / AMD iGPU? First run `ls /dev/dri` on the
# host to confirm it exists (ARM boxes and CPU-only hosts usually don't have it).
# Enable the two lines below without it, and the container gets recreated and then
# fails to start, leaving nothing but "no such file or directory".
# devices:
# - /dev/dri:/dev/dri
# Using an NVIDIA dGPU? It does **not** go through /dev/dri — don't mount that when
# you have no iGPU (the container won't start). Install the NVIDIA Container Toolkit
# on the host first, then enable this line:
# runtime: nvidia
# When in doubt, leave them alone: the first-start log will tell you outright whether
# hardware decoding is available and what's missing.
restart: unless-stopped
Step 2: Point the volumes entries at real paths on your machine. There's one rule
to remember: left of the colon is a directory on your machine; right of the colon
is what MovieClaw sees inside the container — and it's the right-hand path you'll type
into the web UI later. Do mount your download client's save directory, or MovieClaw can't
see finished downloads and can't file them into your library.
The left-hand directory must already exist on the machine. Docker doesn't error on a bad path — it quietly creates an empty folder for you, the container starts fine, the logs look clean, and your library sits empty. Synology users, watch the volume number and the capitalization (
/volume1vs./volume2,mediavs.Media).lsthe directory before you paste, or double-check it in your file manager.
Step 3: From that folder, bring it up (NAS GUI users: Container Manager → Project → Create, pointed at the folder):
docker compose up -d
First start takes about ten seconds on a fast machine, a minute or two on a slower NAS.
Meanwhile the page just shows "connecting to the service…" — that's normal. You'll know
it's actually up when docker logs movieclaw prints 前端反代 已就绪 ("frontend proxy
ready"). If the
command instead fails with
failed to bind host port 0.0.0.0:3000/tcp: address already in use, port 3000 is
taken — see the FAQ.
Step 4: Open http://<host-ip>:3000, follow the wizard to create the admin account,
then:
/media in the example above,
not /volume1/media. Scanning starts immediately; existing files get identified
and scraped, and anything ambiguous waits in pending identification for your
confirmation.
Enter a wrong path and the page still says "scanning" — but it finishes with 0 files
and the results read "root path does not exist, skipped". That line means the path is
wrong.Just want one command to try it out?
docker run -d --name movieclaw --init -p 3000:3000 -p 7359:7359/udp --restart unless-stopped -e TZ=Asia/Shanghai -v "$(pwd)/data:/app/data" -v /volume1/media:/media -v /volume1/downloads:/downloads movieclaw/movieclaw:latestThe mount rules are exactly the same as above.-p 7359:7359/udpis LAN auto-discovery; drop it if Jellyfin / Emby already runs on this host.
From then on, day-to-day upgrades happen in Settings → Updates & Maintenance:
MovieClaw pulls a few-megabyte artifact package from GitHub Releases (mirrors
configurable), applies it on the data volume, and the result survives container
recreation. If an update misbehaves, roll back on the same page — and a genuinely broken
one rolls itself back automatically.
docker compose pull && docker compose up -d is only needed when the release notes
explicitly say an update carries dependency changes and requires a new image. That's rare.
(How it works: in-app-update.md.)
MovieClaw speaks Jellyfin's playback API, so third-party players connect to it as if it were a Jellyfin server — just add the address. Support by client below; "verified on device" means someone actually connected and played on real hardware:
| Client | Status | Notes |
|---|---|---|
| Web player | Built in | Direct play first; transcodes only what the browser can't handle, and tells you the cost before it starts |
| Infuse / VidHub | Verified on device | Connects as a Jellyfin server: browsing, direct play, progress sync — zero changes on the player side |
| Fileball / SenPlayer | Same API | Rides the same Jellyfin-compatible path, but hasn't been individually verified on device |
| Emby / Jellyfin official apps | Not applicable | They connect to their own servers; MovieClaw can notify an Emby/Jellyfin instance to refresh after imports |
| LAN auto-discovery | Yes | Requires mapping 7359/udp. On a bridged network the container doesn't know the host's LAN address: open MovieClaw once in a browser by its LAN address (e.g. http://192.168.1.10:3000) and the server remembers it, or set Settings → Network → External URL |
| Remote hardware transcoding | macOS Apple Silicon | Menu-bar app encoding through VideoToolbox (an always-on Mac mini is plenty). The protocol is open — other platforms can implement it |
Details in jellyfin-compat.md, web-player.md, and remote-transcode.md.
mclaw, MovieClaw's command-line client, is a single static binary — no Python, no Node,
no package manager. Install it on any machine, and that machine can drive your library:
search titles, create subscriptions, monitor jobs, organize files.
On the server itself there's nothing to install — the image already ships it:
docker exec -it movieclaw mclaw status # container name as in your compose file
Everywhere else, it's one command. The installer detects OS and architecture on its own (x86 and ARM, on both Linux and macOS), verifies checksums, and installs into the default PATH — so cron, systemd, and Dock-launched apps can find it too:
curl -fsSL https://raw.githubusercontent.com/movieclaw/movieclaw/main/scripts/install-cli.sh | sh
PowerShell won't pipe into sh, so Windows gets its own one-liner — it installs the same
thing (amd64 and ARM64 both covered):
irm https://raw.githubusercontent.com/movieclaw/movieclaw/main/scripts/install-cli.ps1 | iex
Then run mclaw login to pair. With no arguments it scans the local network first;
across subnets or over a VPN, pass the address yourself
(mclaw login --server http://192.168.1.10:3000). The command displays a pairing code —
verify and approve it in the web UI under Settings → Devices. The
token is handed straight back to the process, never printed, so it never ends up in your
clipboard or shell history.
Where nobody can click "approve" in a browser (NAS cron jobs, CI, headless containers),
use Create token manually on the same Devices page and inject the two lines it gives
you — MOVIECLAW_SERVER and MOVIECLAW_TOKEN — as environment variables. Credentials
never touch disk.
The command tree is generated from the server's OpenAPI spec: add an endpoint to the
backend and the CLI picks up the matching command automatically — no guesswork. Outside a terminal
(pipes, agents), it emits JSON by default, so there are no human-formatted tables to
parse; destructive operations demand an explicit --yes. Any assistant that can run a
shell can drive MovieClaw with it — the built-in AI assistant goes through exactly this
path.
mclaw status # server and auth status
mclaw search titles "Three-Body" # search titles
mclaw subscriptions list # list subscriptions
mclaw jobs list # list background jobs
mclaw library organize-files 1 --yes # organize existing file names in library 1 per the naming template
mclaw subscriptions --help # every domain has --help, listing its commands and flags
Before handing a token to an external agent, read the assistant guardrails: a token carries the same privileges as the person who approved it, and revoking one is a single click on the Devices page.
Run one command on the machine hosting MovieClaw. Nothing else is touched — sites, download clients, libraries, and subscriptions all stay put; only the password changes:
# Docker deployment (container name as in your compose file)
docker exec -it movieclaw python -m movieclaw_api.reset_password
# Source deployment: cd to the project root first (the parent of data/)
python -m movieclaw_api.reset_password
Type the new password twice at the prompt; no restart needed. Forgot the username as
well? Add --show to see it first. To force other signed-in devices out too, follow up
with docker restart movieclaw.
Why there's no "forgot password" link in the web UI: with self-hosting, there's no
trusted third party to vouch that you own the account, and real email recovery would
force every deployer to set up SMTP first. Instead, ownership is proven by something
stronger: whoever can reach this machine's data/ directory owns the server.
Jellyfin, Vaultwarden, and Gitea make the same call.
Family members who forget their passwords don't need any of this — an admin resets them with one click under Settings → Members.
Change the left side of the ports colon — e.g. "8096:3000" — and browse to
http://<host-ip>:8096. The container-side port stays as it is.
Only under --network host does the container port become the host port, and only then
do you actually change the listening port: add -e MOVIECLAW_WEB_PORT=8096, or change it
after setup under Settings → Network (restarts itself on save).
Host networking has a further trap: the container's internal frontend (3001) and
backend (8000) also bind directly on the host. MOVIECLAW_WEB_PORT only changes nginx's
public port. If 3001 is taken, set MOVIECLAW_NEXT_PORT=13001 (or another free port) to
move the internal frontend; the backend still requires port 8000 to be free. With host
networking, remove ports because port mappings are ignored. This frontend port option
requires a new Docker image: pull the updated image and recreate the container; an
in-app update cannot replace the entrypoint or nginx template. Host mode also
listens on UDP 7359 for LAN discovery, which collides with an existing Jellyfin
or Emby.
Bottom line: change the left side of the colon and stay off host networking. LAN
auto-discovery works on a bridged network too (just map 7359/udp).
无法连通 TMDB ("cannot reach TMDB"), ConnectTimeout, CircuitOpenError, or
CERTIFICATE_VERIFY_FAILED — whether in the logs or in the connectivity test under
Settings → Network — all point to the same problem.
If your network can't reach api.themoviedb.org directly, set a proxy or mirror address
under Settings → Network and confirm with the built-in connectivity test. By
default the proxy covers TMDB, artwork fetches, and GitHub updates, while tracker sites
stay on direct connections (usually faster that way).
It runs as root; PUID / PGID aren't supported yet. The database and key files under
data/ are owned by root:root.
Mounted media directories must be writable — filing imports and recycling replaced versions both move files, and a read-only mount breaks those features. If the directories belong to another user on your NAS, root can generally still write there; the friction runs the other way — your own account may lack permissions on directories MovieClaw creates. If that matters to you, loosen the directory permissions on the host before mounting.
Turn off real-time file watching when you create the library. File events over network mounts are unreliable; periodic reconciliation plus a manual scan is far more dependable.
You'll need a free TMDB API key from themoviedb.org — the official image has one baked in; only self-builds need their own.
git clone https://github.com/movieclaw/movieclaw.git
cd movieclaw
TMDB_API_KEY=your_key ./scripts/build-image.sh
# Mirror acceleration for mainland China: CN_MIRROR=1 TMDB_API_KEY=... ./scripts/build-image.sh
# Cross-building for a NAS: PLATFORM=linux/amd64 TMDB_API_KEY=... ./scripts/build-image.sh
The key can also live in a .env at the repo root. Note that .env.example ships the
line commented out (# TMDB_API_KEY=) — drop the # or the script won't see it.
With no key at all, the script fails fast instead of wasting your time on a build.
The build reaches out to deb.debian.org, repo.jellyfin.org, pypi.org,
registry.npmjs.org, and GitHub. On mainland-China networks, add CN_MIRROR=1. Behind
a corporate proxy that intercepts and re-signs TLS, the build dies at
curl ... exit code 60 or pip's CERTIFICATE_VERIFY_FAILED — that's a certificate-trust
problem, not a script bug.
Then point the image: line in docker-compose.yml at movieclaw:latest and start.
As a self-check, the build generates PGS test samples and OCRs them back to SRT, failing
hard on any mismatch. The subtitle runtime and its release gates are described in
docker-subtitle-runtime.md.
First, free up ports 3000 and 8000. If this machine also runs the MovieClaw Docker
container, docker compose down it first — "used the image, now wants to hack on the
code" is the single most common contributor story, and the collision is guaranteed. When
a port is taken, the dev script fails immediately and tells you how to find the culprit
(requires lsof).
./scripts/dev.sh # start backend and frontend together
./scripts/dev.sh api # backend only
./scripts/dev.sh web # frontend only
The script handles first-run setup on its own (virtualenv, dependencies, .env,
pnpm install). Logs carry colored [api] / [web] prefixes, and Ctrl-C tears
everything down cleanly — child processes included, ports freed. Note that it picks the
newest Python it can find for the virtualenv (3.14 → 3.11), which may not be the one
your python3 points at.
Going manual takes two terminals — backend and frontend are both foreground processes:
# Terminal 1: backend (Python 3.11+)
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
uvicorn movieclaw_api.main:app --factory --reload --reload-dir src
Keep
--reload-dir src. By default uvicorn watches the whole working directory, and runtime logs land indata/logs/— so every log write triggers reload detection, the detection writes another log line, and the loop floods the log until it's unreadable../scripts/dev.shpins this for you.
# Terminal 2: frontend (Node.js 20+)
pnpm install && pnpm web:dev
Web console at http://127.0.0.1:3000, API docs at http://127.0.0.1:8000/docs. A
blank .env boots fine — you just lose the TMDB-dependent features.
Changing the backend port means changing it in two places.
APP_PORTin.envmoves the backend, but the frontend's proxy target is hardcoded to default tohttp://127.0.0.1:8000— you must also setMOVIECLAW_API_PROXY_TARGETinapps/web/.env.localto the new port. Change only one, and the page loads while every API call comes back empty. The frontend's own 3000 is hardcoded and not configurable. And on the manual path, a uvicorn port collision says only[Errno 98] Address already in use, withoutdev.sh's friendlier hint.
When running from source, the NER model behind torrent-name parsing needs placing by
hand (the Docker image includes it): download model.int8.onnx, tokenizer.json, and
labels.json from Releases, drop them
into data/models/torrent-ner/ (path configurable via MOVIECLAW_NER_DIR), and restart.
Without the model, the app runs fine — that one feature just stays off. The first time
extraction is actually triggered, the log notes that the model is missing and that
title/year/season/episode fields will stay empty. But that warning is emitted lazily:
it never appears at startup, so a clean boot log is not proof the model is in place.
One more known boundary when running from source: if the process is killed in a way that
allows no cleanup — kill -9, a power cut — while the AI assistant is executing a command,
the subprocesses it spawned may be left running (normal shutdown, timeouts, and the user's
stop button all reap the whole process group, and under Docker a container restart cleans
up as well). After a hard crash on bare metal, a quick ps check for leftovers is worth it.
Deployment questions, setup tips, feature ideas, or just showing off your library — come say hello:
The major design decisions behind every module — and the trade-offs that shaped them —
live in docs/design/, one file per topic: library, metadata, subscriptions,
quality upgrades, Jellyfin compatibility, in-app updates, the CLI… browse by filename.
The reasoning behind this README's own structure is in
readme-rewrite.md.
Third-party plugins, and the store metadata next to each of them (store.json), live in
movieclaw-plugins. How to write one is in that
repo's example/GUIDE.md. The in-app plugin market reads that repo's signed catalog; uploading a .mcplugin file works too.
Questions, ideas, bug reports — please open an issue.
Versions released after v0.27.0 are licensed under the MovieClaw License: the Apache License 2.0 with additional conditions.
v0.27.0 and earlier releases remain under the MIT License. For commercial licensing, please email [email protected].