Imported from hanliang97/MatrixMedia (
.cursor/skills/matrixmedia-cli-publish/SKILL.md). Install upstream withnpx skills add hanliang97/MatrixMedia --skill matrixmedia-cli-publish. Copyright stays with the author.
MatrixMedia CLI
Subcommands
| Subcommand | Platform coverage | Purpose | Writes state? |
|---|---|---|---|
cli login |
Douyin (-p dy) and 视频号 (-p sph) |
Scan-to-login via terminal QR, --show window, or headless puppeteer (Douyin only) |
yes (session cookies) |
cli publish |
All 7 platforms (dy | tt | ks | blbl | bjh | sph | xhs) |
Publish a local video via puppeteer automation | yes (pushData log) |
cli accounts |
All platforms | List all accounts from the GUI account tree and report current login state | no |
cli history |
All platforms | Read local publish records (pushData) with platform/phone/status filters | no |
Douyin and 视频号 support CLI login. Other platforms cannot log in via CLI — ask the user to log in once in the GUI; CLI then reuses the same
persist:<phone><platform>session partition forcli publish/cli accounts. Ifcli accountsreportscookie 已过期, send the user back to the GUI to re-login (or usecli loginfor Douyin/视频号).
Quick Start
Use this skill when the user asks to:
- use CLI mode instead of GUI
- publish videos by command line
- inspect account login status or publish history from the command line
- automate login/publish in OpenClaw or other agent workflows
Default publish sequence:
- Preflight checks
cli accountsto verify the target account is logged in (optional but recommended)cli login(only when needed)cli publish- Verify exit code, optionally
cli history -n 5to confirm the new record - Summarize result
Preflight Checklist
Before running publish commands, ensure:
- current directory is repository root
- video file path exists
ELECTRON_RUN_AS_NODEis not globally forced to1- platform and account identifier are provided
If the user gives incomplete parameters, ask for:
platform(dyfor Douyin as default)phone(preferred) orpartitionfilepathtitle
Canonical Commands
Installed app (recommended) examples:
# show login help
matrixmedia cli login --help
# login (Douyin — terminal QR, no window)
matrixmedia cli login -p dy --phone 13800138000
# login (视频号 — terminal QR, transparent window)
matrixmedia cli login -p sph --phone 13800138000
# login (视频号 — visible window for debugging)
matrixmedia cli login -p sph --phone 13800138000 --show
# show publish help
matrixmedia cli publish --help
# publish
matrixmedia cli publish \
-p dy \
--phone 13800138000 \
-f "/absolute/path/to/video.mp4" \
-t "视频标题" \
--name "任务名" \
--tags "标签1,标签2"
# list all accounts with login status
matrixmedia cli accounts
# list only logged-out Douyin accounts in JSON form
matrixmedia cli accounts -p dy --logged-out --json
# last 7 days of publish records
matrixmedia cli history
# failed publishes on Douyin in the last 30 days
matrixmedia cli history -p dy -d 30 -s failed
Development mode (repo local) examples:
# show publish help in source workspace
ELECTRON_RUN_AS_NODE= electron . cli publish --help
Windows installer behavior:
- NSIS installer writes install directory to user
PATH. - Executable command is unified as
matrixmedia. - Users should not need to choose between Chinese/English executable names.
macOS installer behavior:
-
.dmgonly delivers the.appbundle; it cannot touch userPATH. -
Recommend users run a one-time symlink after drag-installing:
sudo ln -sf /Applications/matrixmedia.app/Contents/MacOS/matrixmedia /usr/local/bin/matrixmediaAfter that, plain
matrixmedia cli ...works in any terminal. The link survives app upgrades as long as the.appstays at/Applications/matrixmedia.app. -
If the user refuses
sudo, fall back to an alias in their shell rc:alias mm='/Applications/matrixmedia.app/Contents/MacOS/matrixmedia' -
When scripting on Mac without the symlink, always spell the full binary path —
/Applications/matrixmedia.app/Contents/MacOS/matrixmedia cli ....
Argument Mapping
Map user intent to CLI args:
-p,--platform: target platform--phoneor--partition: account/session partition-f,--file: local video path-t,--title: required video title--description,--desc: optional video description/body--short-title: optional 视频号 short title, recommended 6–16 characters--name,--book-name: task name--bt2: legacy compatibility; short title for 视频号, description for other platforms--tags,--bq: video tags(space-separated;#prefix semantics vary per platform)--address: location field (Baidu use case)--publish-at: one-time scheduled publish time, formatYYYY-MM-DD HH:mm:ss--show: show automation window--no-close-window: keep window open when--showis enabled
Scheduled Publish
Use --publish-at "YYYY-MM-DD HH:mm:ss" for one-time scheduled publishing. The command must include the real video file and text fields; do not create empty placeholder tasks.
matrixmedia cli publish \
-p dy \
--phone 13800138000 \
-f "/absolute/path/to/video.mp4" \
-t "视频标题" \
--description "视频简介" \
--short-title "短标题" \
--tags "#标签1 #标签2" \
--publish-at "2026-05-05 20:30:00"
Rules:
- Only explicit year-month-day hour-minute-second is supported. Do not generate daily, weekly, monthly, or cron-style schedules.
- The scheduled task is written to publish history immediately with status
scheduled. - If MatrixMedia is closed and misses the time, the next startup marks the task as
expired; do not auto-republish expired tasks. - Failed or expired scheduled tasks can be republished from GUI history because the record stores the real file path, platform, account, title, short title, tags, and address.
- If
--publish-atis in the past or uses an invalid format, treat it as an argument error and ask the user for a future time.
Per-Platform Field Semantics
Use the semantic fields directly:
| Platform | --title |
--description |
--short-title |
--tags |
|---|---|---|---|---|
| 视频号 (sph) | record title | description body | optional separate 6–16 character field | appended to description |
| 抖音 (dy) | title input | description body | unused | appended to description |
| 快手 (ks) | record title | description body | unused | appended to description |
| 哔哩哔哩 (blbl) | submission title | independent introduction field | unused | independent tag widget |
| 百家号 (bjh) | title input | unused | unused | unused |
| 头条 (tt) | title input | unused | unused | unused |
| 小红书 (xhs) | title input | body text | unused | inserted as topic chips after the body |
视频号短标生成规则(最常踩坑)
When publishing to 视频号, accept --short-title from the user or generate one when useful. Rules when generating:
- Length: 6–16 characters (Chinese chars and ASCII letters each count as 1). Aim for 8–12 to be safe.
- Punctuation blacklist (will be replaced with space by the uploader):
,。、/ , ; : ! ? ' " ( ) [ ] { } < >. Avoid entirely, don't try to style with them. - Content: distill the video's core hook / outcome / number — not a truncation of the long title.
- Don't reuse
--titleverbatim; the short-title box should contain a concise summary. - Style: short declarative phrase, optionally an emotional beat or a number, no trailing punctuation.
Good vs bad (long title "新手第一天跑步就坚持 5 公里是什么体验"):
- ✅
"5公里新手挑战"— 7 chars, no punctuation, keeps the hook (number + identity). - ✅
"第一天跑5公里"— 8 chars. - ❌
"新手第一天跑步就坚持5公里是什么体验"— 18 chars, exceeds hint, also redundant with title. - ❌
"第一天!跑5公里!"— punctuation will be stripped to spaces, becoming第一天 跑5公里.
When the user hands over only a long title and asks the agent to publish to 视频号, auto-generate a short title that satisfies the rules, and echo it back in the result summary so the user can audit.
标签写法规范
- 最多 4 个话题。这是 agent 生成
--tags时的硬上限:不管用户给了多少候选,选出最相关的 4 个,多余的丢掉。少于 4 个 OK;不要为了凑数塞弱相关词。CLI 对 > 4 的输入会打 warn。 - 视频号 / 抖音 / 快手 必须带
#前缀。这三个平台把--tags整串拼进描述末尾,不加#就只是普通尾缀文字,不成话题。典型写法:"#减脂 #健身 #新手 #跑步"(4 个,空格分隔,每个前置#)。 - 哔哩哔哩 / 小红书 可不带
#。这俩走独立标签控件,split(/\s+/)后剥前导#;为清晰推荐不写#,数量同样上限 4。 - 百家号 / 头条 不消费
--tags。不要为这两个平台耗费思考生成标签,写也被忽略。 - 分隔符:严格 ASCII 空格。
,,、;;|都会被split(/\s+/)视为标签字符一部分,CLI 会 warn。 - 字符集:中文 / 英文 / 数字;单个标签内部不要空格;哔哩哔哩控件会静默吞 emoji。
- 避免跨字段重复:不要把同一句话同时放入
--description/--short-title/--tags。
Good vs bad(视频号 / 抖音 / 快手):
- ✅
--tags "#减脂 #健身 #新手 #跑步"— 4 个话题,都带#,空格分隔 - ✅
--tags "#跑步 #新手"— 2 个话题也合法,相关性优先 - ❌
--tags "#减脂 #健身 #新手 #跑步 #效率 #自律 #打卡"— 7 个超出上限,agent 应裁到最相关 4 个 - ❌
--tags "减脂 健身 新手 跑步"— 没有#,在这三个平台会变成描述的普通尾缀文字 - ❌
--tags "#减脂,#健身,#跑步"— 逗号分隔,会被当作一个整体串;用空格
Good vs bad(哔哩哔哩 / 小红书):
- ✅
--tags "游戏 解说 开黑"— ≤ 4,无#更直观 - ✅
--tags "#游戏 #解说 #开黑"— 带#也 OK(会被剥离),不推荐
Login Rules
cli loginsupports Douyin (-p dy) and 视频号 (-p sph). Do not attemptcli login -p tt/ks/blbl/bjh— the parser rejects it.- Douyin login: default hidden window + terminal QR; supports
--puppeteer-headlessfor true headless mode.--showis ignored. - 视频号 login: default transparent window (
opacity: 0) + terminal QR; supports--showto open a visible login window. Does not support--puppeteer-headless. UA is injected via CDPpage.setUserAgent()(WeChat UA) before navigation to cover all iframe requests. Re-login is always supported (detects newsessioniddifferent from the old one). - For non-Douyin/视频号 platforms: instruct the user to log in once in the GUI; CLI automatically reuses the same
persist:<phone><platform>session partition forcli publish/cli accounts. - If a publish fails with login/session errors:
- Douyin → run
cli login -p dy --phone <phone>first, then retry publish. - 视频号 → run
cli login -p sph --phone <phone>first, then retry publish. - Other platforms → ask the user to re-login in the GUI, then retry
cli publish.
- Douyin → run
- On Linux headless/SSH, prefer
xvfb-run -afor the login display pipeline. cli accountsis non-interactive — it only reads session cookies and never triggers login; use it to pick the right--phone/--partitionbefore login or publish, and to diagnose expired cookies.
Accounts Command
Inspect login state for every account the GUI already knows about:
matrixmedia cli accounts [options]
Key flags:
-p, --platform <id>: filter by platform (dy|tt|ks|blbl|bjh|sph).--phone <id>: filter by full phone string stored in the account tree.--logged-in/--logged-out: keep only one side (mutually exclusive).--json: machine-readable output (objects withphone/pt/partition/loggedIn/reason/expireAt/createdAt).
Rules used per platform (cookie in the persist partition for that site):
- 抖音 →
passport_assist_user - 百家号 →
BDUSS - 头条 →
odin_tt(value length > 65) - 视频号 →
sessionid - 番茄视频 →
sessionid - 哔哩哔哩 →
SESSDATA - 快手 →
userId
Expired cookies report loggedIn: false with reason cookie 已过期.
History Command
Read the local publish log (<Documents>/MatrixMedia/data/pushData/YYYY-MM-DD.json):
matrixmedia cli history [options]
Key flags:
-p, --platform <id>: platform filter.--phone <id>: phone filter.-s, --status <s>:success | failed | publishing(中文同义成功 | 失败 | 发布中)。-d, --days <n>: look-back window (default 7).--since <YYYY-MM-DD>/--until <YYYY-MM-DD>: explicit range; overrides--days.-n, --limit <n>: cap rows (default 50, sorted by last publish time desc).--json: machine-readable output.
Record-status inference: prefer publishStatus; fall back to publishSuccessCount > 0 → success, publishFailCount > 0 → failed, otherwise publishing. Attempt column shows successCount/attemptCount, matching what GUI 视频管理 renders.
Execution Policy For Agents
- Run
cli <sub> --helponce when flags are uncertain (applies to publish/login/accounts/history). - Quote paths that may contain spaces.
- Prefer absolute file paths for
--file. - Before publishing, run
cli accounts -p <platform> --phone <phone>(or--logged-outvariant) to confirm the session is still valid — it avoids wasting a 35-minute publish timeout on an expired cookie. - After execution, inspect exit code:
0: success2: argument error, fix arguments and rerun3: task failure (often login/session/upload), recover then rerun
- When debugging a failed publish,
cli history --phone <phone> -p <platform> -n 5shows the most recent attempts and thelastPublishMessagethat GUI displays. - Return a concise result summary: command intent, key args, outcome, next action.
Output Template
Use this response structure after command execution:
执行结果:
- 命令:`cli publish ...`
- 参数:平台/账号/文件/标题
- 退出码:0|2|3
- 结论:成功 或 失败原因
- 下一步:是否需要先 `cli login` 或调整参数重试
Additional Reference
- CLI overview:
docs/cli.md - Repository quick intro and OpenClaw marker:
README.md