dldl · agent-downloader
A downloader with no window: you run one command and read one JSON object. Built for an agent to call, used by me every day.没有窗口的下载器:跑一条命令,读一个 JSON 对象。写它是为了让 Agent 能调用,我自己每天在用。
What it does做到了什么
- 19 commands, 23 MCP tools, one JSON contract19 条命令、23 个 MCP 工具,共用一套 JSON 契约
- 28 tests, and the exit codes 0 / 1 / 2 / 130 are part of the interface28 个测试;退出码 0 / 1 / 2 / 130 是接口的一部分
- Portable build: 86.7 MB, Python 3.12, yt-dlp and ffmpeg already inside便携版 86.7 MB,Python 3.12、yt-dlp、ffmpeg 全在里面
- 'done' means the file is on disk, not that progress reached 100%done 的依据是文件真的落到磁盘,而不是进度条到了 100%
- dl doctor prints the exit IP and which sites answer, before you blame the tooldl doctor 先打印出口 IP 和哪些站点能通,再谈是不是工具的错
Screens界面
An agent does not click buttons. It runs a command, then reads whatever came back. dl is a downloader written for that caller: one JSON object on stdout, progress on stderr, and an exit code that carries meaning.Agent 不会点按钮。它跑一条命令,然后读返回的东西。dl 就是为这个调用方写的下载器:stdout 只吐一个 JSON 对象,进度走 stderr,退出码带含义。
The contract came before the commands先定契约,再写命令
One rule shaped the whole program: stdout carries exactly one JSON object and nothing else. Everything a human would want - bars, warnings, spinners - goes to stderr. That single decision is why the same build works as a CLI, as an MCP tool for a coding agent, and inside a script that pipes the result somewhere else.一条规则决定了整个程序:stdout 只允许出现一个 JSON 对象,别的什么都不许有。人想看的东西——进度条、警告、转圈——全部走 stderr。正是这一条,让同一份程序既能当 CLI、又能当编码 Agent 的 MCP 工具、还能塞进一条把结果转给别人的管道。
Failure has to be legible失败的方式必须是可读的
Most download failures are not the tool's fault: the site is blocked, a login is required, the link expired. A downloader that only says failed sends the caller guessing. dl separates the cases - doctor reports the exit IP and which sites answer, and every failure carries a reason label rather than a stack trace.大多数下载失败不是工具的错:站点被墙、需要登录、链接过期。只会说「失败」的下载器会让调用方瞎猜。dl 把这些情况分开——doctor 报告出口 IP 和哪些站点能通,每种失败带原因标签,而不是甩一段堆栈。
'done' means the bytes landeddone 意味着字节真的落地了
Progress at 100% is not the same as a file that exists. The done state is driven by yt-dlp's after_move hook, so the card only turns green when the file has actually arrived at its final path - which matters most exactly when a download is interrupted.进度到 100% 不等于文件存在。done 状态由 yt-dlp 的 after_move 钩子驱动——只有文件真的到了最终路径,卡片才变绿。这一点恰恰在下载被打断时最要紧。
A tool for an agent has to fail in a way the agent can read.给 Agent 用的工具,失败的方式必须是它能读懂的。Design note设计笔记
- 19 commands, 23 MCP tools, one JSON contract19 条命令、23 个 MCP 工具,共用一套 JSON 契约
- 28 tests, including exit-code and idempotency cases28 个测试,含退出码与幂等用例
- Portable build - unzip, double-click, no Python on the target machine便携版:解压、双击,目标机器不需要装 Python
- Windows 10/11, version 2026.10.16Windows 10/11,版本 2026.10.16