命令行指南
在服务器、NAS 或一条 SSH 会话里用 swarmdrop 收发文件。
swarmdrop 是 SwarmDrop 的第四个客户端,与桌面、移动、浏览器共用同一份 Rust 内核、
同一套配对协议、同一种加密与验签。它不是桌面端的遥控器,而是一个完整的传输端点——
为没有屏幕的机器而存在:服务器、NAS、一条 SSH 会话,以及需要脚本调度传输的场合。
安装
brew install swarm-apps/tap/swarmdrop # macOS · Linux
npm install -g swarmdrop # 有 Node 的地方都行也可以直接跑安装脚本(Windows 用 PowerShell 那条),命令在
最新 CLI release
页面里。安装后 swarmdrop --version 应能打印版本号。
升级用 swarmdrop update。
它认得出自己是怎么被装的:安装脚本装的那份就地更新,用 Homebrew 或 npm 装的会转交给
对应的包管理器(brew upgrade swarmdrop / npm install -g swarmdrop@latest)而不是硬更新
——不去和它们争「当前版本是哪个」。swarmdrop update --check 只查不装。
更新前需要先 swarmdrop stop:正在跑的节点占着这个可执行文件。
第一次传输
启动节点
swarmdrop start默认前台运行——systemd / launchd 这类服务管理器要的就是前台。想让它转后台并立即返回,
加 -d。
首次启动会生成本机的 Ed25519 设备身份,不需要设任何密码。启动后的输出里有节点标识、 监听地址和接收落点。
配对设备
两个方向任选其一。
由本机发起——生成一张邀请交给对方(另一台机器的图形端扫码或粘链接都行):
swarmdrop invite create它生成邀请后会一直守着,直到有设备用它配对成功,或你按 Ctrl-C 中断。这不是偷懒的 阻塞式实现:入站配对必须由人核对后放行,而配对窗口只在这条命令运行期间打开。 邀请会经聊天工具、剪贴板辗转到对方手上,路上可能被别人看到;它又是一次性的,被抢先用掉 那次就消耗掉了凭证,真正的设备再来就配不上。
由对方发起——把对方给的邀请串交给本机消费:
swarmdrop invite use "<邀请链接>"配对是一次性动作,配完即长期信任,之后传文件不必再确认身份。
发送
swarmdrop send ./photos ./report.pdf --to laptop--to 认设备名,也认节点标识。两个参数都可以省——省了就列出已配对设备让你选、
逐行问你要发什么。
发一段文本
同一条命令也能发文本,加 --text 即可。对端在收件箱里收到它,不是文件。
swarmdrop send --text "构建挂在第 3 步了" --to laptop只给 --text 不给内容时,正文从别处取——取决于标准输入是不是终端:
pbpaste | swarmdrop send --text --to laptop # 管道:读到 EOF
tail -50 /var/log/nginx/error.log | swarmdrop send --text --to laptop
swarmdrop send --text --to laptop # 终端:拉起 $EDITOR 写编辑器那条是给多行正文准备的:上限 64 KiB,而一个单行输入框连回车都收不下。 留空缓冲区退出即放弃发送。
成功时命令说的是**「已送达」**而不是「已发送」——它一直等到对端确实把正文存下来才返回。 对端的设备策略要求人工确认时(新配对设备的默认档位就要求),这条命令会等在那儿, 最长五分钟;期间屏幕上有一个转轮说明它还活着。
命令行端自己不需要确认:节点在线时它自动收下已配对设备发来的文本,与文件同一条规则。
正文原样送达——缩进、空行都保留,只有结尾的换行会被削掉(echo 加的那个)。
读回来用:
swarmdrop inbox list
swarmdrop inbox show <条目> # 打印完整正文
swarmdrop inbox export <条目> ./out # 写成 <条目>.txt接收不需要命令
节点在线期间,已配对设备发来的传输会被自动接受并落盘。这与图形三端不同:那边有收件箱 让人逐条决策,而命令行端没有界面可以弹确认框,等一个不会到来的人工确认只会让对端一直卡在 「等待接受」。判据是已配对——能发起传输的对端必然已经过配对握手,那一步才是信任边界。
落点默认是 <系统下载目录>/SwarmDrop。改它有两个办法,环境变量优先:
swarmdrop config set receive-dir /srv/incoming # 持久化,跨重启有效
export SWARMDROP_RECEIVE_DIR=/srv/incoming # 只影响这个进程,但优先级更高环境变量排在前面是刻意的:命令行端常跑在脚本与服务单元里,那些地方设一个变量比维护一份
配置自然得多。两者同时存在时 config list 会明说哪个在生效、以及被压住的那个是什么。
有常驻节点在跑时改落点当场生效,不必重启它;已经收下的文件留在原处不动。
SWARMDROP_RECEIVE_DIR 不经 shell 展开(~ 除外,那个会展开)。别写通配符,路径里的
空格就是路径的一部分,不必也不要加引号转义。config set receive-dir 同样把整串当一个路径。
收到的东西同时进本机收件箱:
swarmdrop inbox list
swarmdrop inbox show <条目>
swarmdrop inbox export <条目> ./somewhereinbox show 的位置一行就是东西落在哪儿——单文件条目给文件自身的完整路径,
多文件条目给容器目录。transfer show 对接收方向也给位置,但粒度恒为容器目录
(它手上只有会话级的信息,没有逐文件的路径);发送方向不给这一项,因为本机没有落点。
落点被 SWARMDROP_RECEIVE_DIR 改过、或忘了当初启动时打印的那一行时,从这里查。
命令一览
| 命令 | 做什么 |
|---|---|
start · stop · status | 节点生命周期;status 还报 NAT 与中继可达性 |
invite create · use · list · revoke | 配对邀请:生成并守着、消费、清点、撤销 |
device list · forget | 已配对设备 |
send | 向一台已配对设备发文件或目录;--text 改发一段文本 |
inbox list · show · export | 收件箱 |
transfer list · show | 传输记录 |
transfer watch | 实时进度面板,p / r / c 就地暂停、恢复、取消 |
transfer pause · resume · cancel | 同样三个动作,也可以直接下命令 |
config list · get · set · unset | 本机设置:设备名、接收落点 |
bootstrap list · add · remove | 引导 / 中继节点 |
update | 更新到最新版本;--check 只查不装 |
每条命令都能不带参数运行,缺什么问什么——不必先读 --help 才敢试。给了参数就按参数走,
不再打断你。
设置
两组,按被配置的东西是一个值还是一份清单分开。
一个值:config
swarmdrop config list # 全部设置项 + 每项的值从哪来
swarmdrop config set device-name "书房 Mac" # 对端看到的名字
swarmdrop config get receive-dir # 只打印值,来源说明走 stderr
swarmdrop config unset receive-dir # 回落到默认一个值可能有三个来源,优先级由高到低是环境变量 → 你设的 → 内置默认。
--json 下每一项都带 source,被环境变量压住时还带上 configured(你设的那个值)与
overriddenBy(压住它的变量名)——所以界面能说清「你改的这个现在还不算数,因为 …」,
而不是让你对着一个不生效的输入框反复改。
被压住时写入仍然成功:那是对未来的声明,取消掉那个变量就会用上。
两项都不要求重启节点。 节点在跑时改名当场生效,对端不必重连就看到新名字。
一份清单:bootstrap
引导 / 中继节点是跨网互通的入口。内置几条自建的,你可以加自己的、也可以撤掉内置的:
swarmdrop bootstrap list
swarmdrop bootstrap add /ip4/203.0.113.9/udp/4001/quic-v1/p2p/12D3KooW...
swarmdrop bootstrap remove /ip4/203.0.113.9 # 前缀够唯一就行;不给则列出来让你挑记下来的是你做了什么(加了哪几条、撤了哪几条),不是合并后的清单——所以将来版本更新 换掉内置地址时,你照样拿得到新的。
添加只做零网络成本的检查(地址能不能解析、有没有 /p2p/、这个传输本端拨不拨得动、
是不是重复了)。「能不能连上」不在提交时回答——加完用 bootstrap list 看,每条会显示
连接与中继状态,连不上时带着错误原文。节点在跑时增删当场生效。
清单可以清空到零条(只在局域网内用是合理的),那之后 list 与 status 都会提醒你此刻
跨网不可达。
实时盯着传输
send 自己就会显示进度(准备与传输两段,无论节点是常驻的还是临时起的)。这个命令盯的是
别的传输——后台收到的、以及之前发起还没结束的。
swarmdrop transfer watch每条未结束的会话一行进度条。正在传的那条显示速率与剩余时间;等待确认、已暂停、已中断的 只显示状态——给它们画一个「0 B/s、剩余 ∞」是在报告一个假事实。
面板上按 p / r / c 会弹出一个多选菜单,列出此刻能做这个动作的会话:暂停只列
正在传的,恢复只列可续传的,取消只列尚未结束的。菜单里出现的每一条都当真做得成。
没有常驻节点时它照样能开——列出的是等着续传的那几条,正是你此刻该知道的事。这时按 p
会就地报一句「先 start」,面板不退。
给人用,还是给脚本用
两个全局开关,方向相反:
| 开关 | 语义 |
|---|---|
--json | 结果以机器可读格式写 stdout,进度与诊断始终走 stderr。同时禁用一切交互提示——它声明的是「调用方是程序」 |
--no-input | 只是不弹提示:缺参数直接以用法错误退出,等待配对期间收到的入站请求一律拒绝(fail-closed) |
start --auto-accept 与 --no-input 方向相反,别混着理解:前者是 fail-open(不问但放行),
后者是 fail-closed(不问就是不放行)。两者同时给出时 --auto-accept 生效——它是对配对行为的
明确指令,而 --no-input 只声明不弹提示。
--auto-accept 默认关闭,理由同上文的「配对窗口」:邀请会泄露,而它是一次性的。
常驻节点与只读命令
start 起来的那个节点是常驻的,其余命令经数据目录下的本地通道复用它,不会各起一个。
只读命令压根不启动节点——device list、invite list、inbox list、transfer list
这些直接读本机记录,没有常驻节点时也是秒回,不会花几秒去连引导节点。
反过来,transfer pause / resume / cancel 要求常驻节点在跑,且绝不为它们起临时节点:
它们动的是活传输,临时节点里空空如也。没有节点时它们立刻报错并告诉你先 swarmdrop start。
独立的设备身份
命令行端与同一台机器上的桌面端是两台不同的设备,各有各的身份、各有各的配对表与数据库。 它们的数据目录刻意分开:
| 平台 | 命令行端数据目录 |
|---|---|
| macOS | ~/Library/Application Support/com.yexiyue.swarmdrop-cli |
| Linux | ~/.local/share/swarmdrop-cli |
| Windows | %LOCALAPPDATA%\yexiyue\swarmdrop-cli\data |
共用目录会让两个进程抢同一份私钥和同一个数据库。所以如果你想在自己的桌面端和自己服务器上的 命令行端之间传文件,需要像对待任意两台设备那样先配一次对。
用 --data-dir 或 SWARMDROP_CLI_DATA_DIR 可以指定别的位置——一台机器上跑多个互不相干的
身份时用得上。目录会被设为仅本人可读(unix 0700)。
已知限制
- 接收需要节点在线。 没有
swarmdrop start跑着,对端发起的传输无人应答。 长期使用请把它交给 systemd / launchd 托管(默认前台正是为此)。 - 入站配对只在
invite create运行期间可能发生。 这是刻意的,见上文。 - 命令行端不参与图形端的收件箱决策流程:已配对设备发来的东西直接落盘。 不想要这个行为,就别让那台设备保持配对。
- 发出去的文本没有重发入口。 一条文本以「未能确认送达」收尾时(退出码 4 或 5——4 是没送到对端、可稍后重发, 5 是对端收到了但没保存), 它的确切去向是不确定的——对端可能已经存下、只是回执没回来。重跑一次命令会新建 一条投递,因此对端有可能收到两份。图形三端在这种情况下提供按原记录重试的入口, 命令行端还没有。