mcpField
W
wonda-cli

wonda-cli

github.com/degausai创意与媒体15974.6k 次安装今天更新
代码仓库

关于 wonda-cli

Wonda CLI 是面向终端 Agent 的内容创作工具包,适合需要通过命令生成、编辑和发布媒体内容的用户。它也提供针对 LinkedIn、Reddit 和 X/Twitter 的研究与自动化能力。

主要功能

  1. 01生成图像、视频、音乐和音频
  2. 02编辑与组合媒体内容
  3. 03向社交平台发布内容
  4. 04研究和自动化 LinkedIn、Reddit 与 X/Twitter
  5. 05JSON 输出及字段筛选

适用场景

  1. 01通过终端 Agent 生成媒体素材
  2. 02编辑并组合已有媒体
  3. 03将内容发布到社交平台
  4. 04自动化 LinkedIn、Reddit 或 X/Twitter 研究

MCP 相关

可通过本地 stdio MCP 路径供客户端调用;MCP 执行与 CLI 相同的命令。远程连接器也可借助本地 relay 在用户的 Mac 上执行操作。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/degausai/wonda --skill wonda-cli

安装后在 Claude Code 中输入/wonda-cli确认已加载。

详细介绍

Wonda CLI

Wonda CLI 是一款面向终端 Agent 的内容创作工具包。可用它生成图像、视频、音乐和音频;编辑和合成媒体;发布到社交平台;以及在 LinkedIn、Reddit 和 X/Twitter 上进行研究和自动化操作。

安装

如果在 PATH 中找不到 wonda,请先安装。推荐使用经过签名的桌面安装程序(CLI + 托盘图标 + 常驻中继,无需额外步骤):macOS 使用 brew install --cask degausai/tap/wonda-app(或从 releases 下载 wonda-macos.pkg),Windows 使用 winget/wonda-windows-setup.exe。下面的 CLI 专用安装渠道适用于所有平台,之后可通过 wonda app install 安装桌面应用:

# npm
npm i -g @degausai/wonda

# Homebrew
brew tap degausai/tap && brew install wonda

设置

  • 身份验证:运行 wonda auth login(会打开浏览器,推荐)或设置 WONDA_API_KEY 环境变量
  • 验证:运行 wonda auth check
OAuth 连接器身份验证

Claude web 和 Cowork 连接器使用 Wonda 的 OAuth 2.1 流程,而不是 CLI API 密钥字段。连接器通过浏览器登录 Wonda,授予所请求的账户访问权限,并接收绑定到 Wonda API 资源的 OAuth 令牌。服务器仅在 Wonda 内将这些令牌换成账户的内部 API 密钥,因此 Agent 和连接器主机都不会看到 sk_... 密钥。对于 CLI 和本地 stdio MCP 路径,请继续使用 wonda auth login 或 WONDA_API_KEY。

Claude Cowork 本地中继

Claude Cowork(桌面应用)会在主机上运行本地 MCP 服务,因此可以直接加载 .mcpb 捆绑包或本地 stdio wonda-mcp 配置,包括写入 WAB 的内容(已于 2026-07-07 验证)。Claude web 无法做到这一点。Wonda 本地中继是另一种途径:它可让远程连接器(web 或 Cowork)在用户自己的 Mac 和住宅 IP 上执行操作,无需任何本地 MCP 配置:

  1. 登录后打开 https://wonda.sh/download,并安装经过公证的 Mac 安装包。
  2. 使用 wonda relay pair 或首次运行时的浏览器交接流程配对中继。此流程使用现有的 cli-auth 流程,并将中继专用的 wrelay_... 凭据存储在 macOS Keychain 中。不要让用户粘贴 API 密钥或设备代码。
  3. 打开 https://wonda.sh/setup,通过有头本地 WAB 连接 LinkedIn、X 和 Reddit,然后在 Claude 中批准一次 Wonda 连接器。

引擎策略为 auto | my_machine | cloud。auto 会在本地中继在线时使用它,否则使用云端。my_machine 不得静默回退:如果中继离线,请询问是否切换到云端。

组织与支出上下文

Wondercat 组织是共享钱包,各自拥有成员席位和计费方式。 成员可以通过切换上下文,从组织钱包(而非个人额度)支出:

  • wonda organizations list(别名:wonda orgs list、wonda org list)—查看你所属的所有组织,以及你在各组织中的角色和席位方案。
  • wonda use --org <slug> —为这台机器设置固定的组织上下文。每个请求都会设置 X-Wonda-Org;额度预留、扣费和 wonda balance 都会通过组织钱包处理。
  • wonda use --personal —切回个人上下文。
  • wonda usage —查看指定时期的支出用量摘要(总计 + 按模型 + 按项目细分)(使用 --month 2026-05 或 --from/--to;默认为当前月份,时区为 UTC)。--project <name> 可将报告限定为一个项目。在组织上下文中,此命令会报告整个组织的用量,包括按成员细分的数据——需要管理员/所有者角色。管理员还可以从网页上的组织页面下载完整的 Excel 报告。
项目(支出标记)

项目可将支出归属到指定工作流,以便进行监控。Agent 应在任务开始时检查当前项目(wonda use 会显示该项目);如果操作人员按项目监控支出,则每项任务都应设置一个项目:

  • wonda use --project <name> — 持续生效:之后的每笔费用都会带上项目标记(显示在 wonda usage、API 和组织 Excel 报告中)。wonda use --no-project 会停止标记;切换组织/个人上下文时会自动清除项目(项目按范围划分)。
  • 在任意命令中使用 --project <name> — 仅覆盖本次调用。
  • wonda project list|create|delete — 管理当前范围内的项目注册表。组织项目仅限组织管理员/所有者创建;个人项目可自行创建。对不存在的名称进行标记会失败并返回 unknown_project(不会静默创建新分类,因此拼写错误不会拆分监控数据)。

wonda topup 始终为你的个人钱包充值,无论当前处于何种上下文。为组织钱包充值(以及配置自动充值)仅限管理员操作,需在网页上的 /organizations/<slug> 完成。如果成员的组织额度用尽,错误信息会提示他们联系管理员或切换回个人账户;他们无法通过 CLI 为组织钱包充值。

组织内的角色与席位计划相互独立:

  • 所有者:组织的原始创建者。不能被降级或移出组织。可在组织页面将所有权转让给其他成员(较少见)。
  • 管理员:可以邀请成员(单独邀请或粘贴批量邀请)、移出成员、更改角色、更改席位、充值、配置自动充值、更改月度限额。
  • 用户:只能使用组织钱包中的额度(如果管理员设置了每位成员的月度限额,则受其限制)。

付费组织席位(WONDA / WONDA_PREMIUM)可获得与个人付费计划相同的付费功能(技能等),但仅在组织上下文中有效。wonda use --personal 会切换为用户的个人账户计划。

访问层级

Wonda 仅提供付费服务:所有产品功能都需要付费套餐,包括 API 调用、本地平台读取、浏览器自动化、媒体合成、文件编辑、诊断、生成、发布、抓取、分析、技能、relay 运行和云端双生。在任何产品命令执行操作前,CLI 都会向 Wonda 实时检查访问权限。无法验证访问权限时,检查将默认拒绝。新账户在订阅前无法使用任何产品功能,账户中有正余额也不能代替套餐。

层级访问权限
匿名(未登录)无产品访问权限。认证、配置、定价、组织发现/选择、Shell 补全和本地关闭命令仍可用,方便用户订阅、恢复访问或停止后台服务。运行 wonda auth login,然后订阅。
免费(已登录,无付费套餐)无产品访问权限。请访问 https://wonda.sh/account 订阅以使用产品。
WONDA($19.99/mo,“Pro”)除云端双生外的所有功能:生成(image/generate、video/generate、……)、媒体上传/下载、发布、抓取、分析、视频分析、技能(wonda skill install/list/get)、转场、剪辑、电子邮件、reddit/LinkedIn 账户创建、样式和品牌。
WONDA_PREMIUM($49.99/mo,“Premium”)WONDA 的所有功能,另加 云端双生(wonda twin:配置、计划运行、流式登录),并提供反检测/防影子封禁保护、无上限和美国账户创建。
受限功能(按账户设置的 PostHog 熔断开关)已包含在付费套餐中,但仍可通过按账户设置的标志进行限制:wonda reddit signup(redditAccountCreationEnabled)、wonda email(emailServerApiEnabled)、公开 LinkedIn 个人资料信息补全(linkedinProfileEnrichmentEnabled)。

如果命令返回 403(paid_plan_required),请访问 https://wonda.sh/account 订阅。

这同样适用于本地 stdio MCP 路径,因为 MCP 执行的是同一个 CLI。平台 Cookie 和数据仍保留在设备上,但命令必须先从 GET /api/v1/auth/access 获得成功的付费访问权限判定。仅使用 relay 的安装可以使用其限定范围的 wrelay_... 凭据进行该权限检查。此限定范围凭据仍无法调用普通账户 API。

声音克隆

从时长不少于 10 秒的音频片段克隆声音,并将其用于 TTS。硬性上限:每个账户最多克隆 20 个声音。费用:每次克隆 $1.50。

# Clone from a local file (auto-uploads to media library first)
wonda voice create "Andu" --file ./sample.mp3 --description "My voice"

# Clone from existing wonda media
wonda voice create "Brand" --media-id <uuid>

# Optional source-audio preprocessing
wonda voice create "Clean" --file ./raw.wav --noise-reduction --normalize-volume

# List cloned voices (each row reports isExpired and expiresInDays)
wonda voice list

# One voice
wonda voice get <voice-id>

# Rename / re-describe (local only, no provider call)
wonda voice update <voice-id> --name "New Name" --description "..."

# Delete
wonda voice delete <voice-id>

在 TTS 中使用克隆的声音:将 voice get 返回的 providerVoiceId 作为 voiceId 传递给 /audio/speech:

wonda audio speech "Hello world" \
  --model minimax-speech-2-8-hd \
  --params '{"voiceId":"<providerVoiceId>"}'

7 天后过期:克隆的声音如果在 7 天内未用于 TTS,将自动过期。使用克隆声音运行 TTS 会自动延长其有效期。过期的闲置声音必须重新克隆(再次支付 $1.50)。

凭据库

持久保存通过外部平台(Instagram、TikTok、Twitter 等)创建的登录信息,以便下次运行时重复使用。密码使用服务器端密钥通过 AES-256-GCM 加密,且仅在执行 get 时解密。

# Create
wonda credentials create --website instagram.com --username myhandle \
  --email [email protected] --password-stdin <<< "hunter2" \
  --metadata '{"signup_source":"wonda-email"}'

# List (passwords omitted)
wonda credentials list --website instagram.com

# Get full record including decrypted password
wonda credentials get <id>

# Update any field (use --password-stdin to rotate; --username "" to clear)
wonda credentials update <id> --username newhandle

# Delete
wonda credentials delete <id>

# Fetch + record why you're using it in one call — POST, not GET, because
# it writes a 'used' event with the reason. Prefer this over `get` whenever
# you can articulate the reason.
wonda credentials use <id> --reason "instagram signup flow"

# See recent events (created / used / rotated / updated) for audit
wonda credentials events <id>

字段:website(必填 — 像 insta 这样的输入会规范化为 instagram.com)、username、email、password(必填)、metadata(任意 JSON)。username / email 至少要提供一个。同一 (website, username) 可以有多条记录 — 如有需要,请自行去重。

事件日志:每次 credentials get/use、create、密码轮换及其他更新,都会作为事件记录在凭据上(操作者:cli | web | system)。使用 credentials events <id> 或 Web UI 中的历史记录图标进行审计。事件日志仅允许追加,删除凭据时会级联删除。

全局输出标志

所有命令都支持以下输出控制标志:

  • --json — 强制使用 JSON 输出(stdout 被管道重定向时会自动启用)
  • --quiet — 仅输出主要标识符(任务 ID、媒体 ID 等),适合脚本使用
  • -o <path> — 将输出下载到文件(隐含 --wait)
  • --fields status,outputs — 选择特定 JSON 字段
  • --jq '.outputs[0].media.url' — 使用 jq 表达式筛选 JSON 输出
CLI 公告与弃用警告

每次执行命令时,CLI 都会轮询 GET /api/v1/updates(匿名访问,在 ~/.wonda/state.json 中缓存 1 小时)以获取有效公告:弃用通知、事件预警、升级提示。消息只会打印到 stderr,因此 stdout/JSON 可保持干净,便于管道传递。

每个请求的弃用提示通过标准 Warning: 299 - "<message>" HTTP 标头传递,CLI 的 HTTP 客户端会将其作为 [deprecated METHOD /path] <message> 输出到 stderr。

使用环境变量 WONDA_QUIET=1 或标志 --quiet 可同时关闭这两类消息。使用 WONDA_NO_UPDATE_CHECK=1 可仅禁用网络检查。

WAB / Wonda Automation Browser(wonda wab)

Claude/Codex 及其他 Agent 默认在后台启动。 使用 wonda wab start <persona> 和不带 --visible 的常规平台命令;这与 Dock 菜单中的 Send to background 状态一致。仅在有意检查界面或手动登录时显示 WAB。wab show/hide 只影响当前会话,不会更改下次启动的默认设置。wab config set <persona> visible true 是有意进行的持久启用操作。常规重复使用会保留可见状态和已选标签页,显示窗口也会保留该标签页。

本地 CAPTCHA/身份验证检测会报告阻止操作的原因,但不会显示浏览器,也不会抢占键盘焦点。请通过经授权的渠道通知操作人员,并提供确切的 wonda wab show <persona> 命令;由他们决定何时显示浏览器。明确的显示/登录命令和托管的流式登录仍会按要求保持可见。

从 CLI v1.66.0 起,macOS 上的 persona 可见性使用 AppKit,无需逐个 persona 授予 Automation 提示权限。 WAB 会通过 PID 隐藏、显示和激活自身的浏览器应用,不会向 System Events 或 persona 应用发送 Apple Events。这也涵盖了原生主机回退保护。已经运行的旧版驱动程序会继续使用旧保护,直到在安全时机重启该 persona;重启活动会话前,请先与其负责人协调。 1Password 已包含在本地 WAB 配置中。 WAB 会下载官方稳定版 1Password 浏览器扩展,验证其发布者签名,并在首次设置时将其固定到工具栏。使用 wonda wab show <persona> 打开 WAB,然后点击 1Password 登录。每个 persona 都会保留各自的 1Password 会话。桌面应用可能需要你批准将 WAB 设为额外的浏览器;直接在扩展中登录也可以。缓存的扩展文件可离线使用。每个 persona 启动时,WAB 至多每天检查一次缓存扩展的更新,包括检查失败的情况;更改 Chromium 版本会触发另一项兼容性检查。如果扩展从未成功安装,每次启动时都会重试安装。已运行的浏览器会在下次启动时获取扩展更新。捆绑的扩展发生变化时,WAB 会刷新其后台 Service Worker,防止 Chromium 重用上一版本的代码。这会保留 persona 的 1Password 登录状态和保险库数据。启动时和运行 wab install 时,会清理超过七天且未使用的缓存版本;正在运行的 WAB 进程所用的版本会保留。启动 WAB 前设置 WAB_ONEPASSWORD=0,即可跳过捆绑的扩展。匿名捕获、临时会话和云端双生实例不会加载该扩展。Wonda 数据路径包含逗号时,也会跳过 1Password,并在驱动程序日志中发出警告;请使用不含逗号的 WONDA_HOME 路径来启用扩展。增强型安全浏览或管理员策略也可能阻止自动加载扩展;WAB 会在其驱动程序日志中报告 Chromium 的拒绝信息,并保留你的浏览器设置。

Wonda Automation Browser(WAB)是一款高级隐身反检测浏览器,经过强化,使平台无法将其识别为自动化程序。wonda wab 是用于反检测 Chromium 技术栈(一个未被检测到的 Playwright 分支)的单一命令。它有两种用途:

  • 已认证会话。 每个 persona 对应一个持久的有头 Chromium,会保留 LinkedIn、X、Reddit 等平台的登录会话。CLI 会按需启动它,让它在空闲一段时间后退出,并在命令运行 --via wab 时通过它路由平台读写操作。Cookie 存储在 persona 的 Chromium 配置文件中,而非 ~/.wonda/config.json。
  • 匿名捕获。 wonda wab screenshot <url>、wonda wab record <url> 和 wonda brand extract 会驱动一个临时 Chromium,它具有全新的指纹,不关联任何 persona,也不包含任何 Cookie。截图支持响应式单张、批量和清单捕获。请参阅下方的截图和录制区块。

概念模型:你拥有多个账号(每个平台一个身份)。每条平台命令都会通过以下方式之一,将请求路由到相应账号的 Cookie:扁平 JSON 存储(--via cookies,速度快,不使用 Chromium),或账号的 persona(--via wab,使用实时反检测 Chromium)。persona 是一个 Chromium 容器,可在单一指纹下容纳多个账号。几乎所有情况下,首次使用 --via wab 时都会自动创建 persona,并以账号名称命名,因此你无需输入 persona 名称。

本地 wonda.mcpb 桌面扩展通过 Claude Desktop 或 Claude Code 使用同一条本地 WAB 路径:平台 Cookie 保留在设备上,读取操作使用本地 Cookie,写入操作使用本地 WAB。Claude 网页版和 Cowork 则需要使用远程 MCP 连接器。 新角色默认使用原生登录。 wonda wab login <persona> <platform> 会打开一个有头 WAB 窗口,你可以在其中登录。会话是在 WAB 内部创建的,因此彼此独立(在其他 Chrome 中退出同一账号不会撤销此会话),而且 Cookie 是在 WAB 自有指纹下生成的,因此会话与浏览器身份保持一致。首次使用 --via wab 时在 TTY 上自动创建的新角色会直接进入此流程。登录 X 后,Wonda 会检测已登录的 screen_name,并将其记录为角色的 X 账号绑定。现有绑定绝不会被静默更改;检测到不同的账号名时会发出警告。从其他浏览器粘贴 Cookie(wonda linkedin auth set、wonda x auth set 等)仍然可用,是明确提供的备用方案;但在全新的 WAB 指纹上手动粘贴 li_at 风险最高。

wonda wab install                             # one-time: npm install + stealth-browser Chromium (shared by sessions, screenshot, record, brand extract)
wonda wab update                              # refresh the runtime to the version this CLI pins (runtime versions ship inside CLI releases): staged download, verified, then atomically swapped in, so a failed download leaves the current driver tree untouched; refuses the runtime swap while personas run (wab stop them first; the relay picks the new runtime up on its next spawn, no restart), while an already-current tree's cheap manifest refresh proceeds without the gate: it reconciles drifted current files back to this build's embedded bytes (additive rewrites, safe under a running persona) and only prunes stale files when NO personas are running, deferring the prune (and keeping the mismatch visible) until the tree is quiet; --check reports installed vs pinned without changing anything, --force reinstalls even when current and re-downloads the shared Chromium build (corrupt-cache recovery; caveat: --force clears the cached Chromium before re-downloading, so a failed forced download leaves the shared cache without it until a retry succeeds). The driver tree also carries a manifest recording what produced it: the embedded driver asset identity compatibility is actually keyed on, plus the CLI build and platform as provenance. A tree whose recorded assets differ from this binary's embedded set (or that predates manifests) is refreshed automatically at the next browser spawn or wab update; two builds shipping byte-identical driver assets share one manifest without churn, so the recorded CLI version can lag behind the newest compatible binary. --check reports the manifest state (ok|absent|mismatch|unreadable) without touching anything; --json only changes the output format and still performs the update
wonda wab start [account]                     # spawn (offscreen by default; --visible to show)
wonda wab stop [account]                      # graceful shutdown
wonda wab show [account]                       # peek a background WAB on-screen to watch it (suspends the macOS focus guard); starts it offscreen first if needed
wonda wab hide [account]                       # send a surfaced WAB back offscreen, resume silent background operation
wonda wab screenshot [persona]                 # persona mode: capture an already-open tab without surfacing it; --json still returns inline base64, --output writes a file, --tab/--full-page optional
wonda wab screenshot <url> --output page.png   # anonymous PNG in a fresh ephemeral browser; responsive waits, injection, animation, element, clip, batch, manifest, and diagnostic JSON controls, see below
wonda wab browse [url] --persona <persona>     # load a page and scroll it like a person: pause, scroll, pause, scroll; stops early once the scrolled element stops advancing, see below (plain text output, not JSON)
wonda wab snapshot -i --persona <persona>      # drive ANY page: interactive elements with refs ([ref=e5]); then click/type/scroll/... @e5, see "Drive any page" below
wonda wab menubar                              # Tray control, macOS menu bar or Windows notification area: the Wonda cat icon with a corner status badge. Green filled = running here and serving; orange half = standing by, which proves only that this machine is not the active device (whether another device or no device is serving is a separate three-way the badge cannot answer, and the menu's detail line only echoes the last relay-health check, a snapshot that can lag while this machine stays in standby); red triangle = running but cannot serve; grey hollow = not running here. The badge carries shape as well as color (filled/half/triangle/hollow) on both platforms; macOS falls back to a 🐱 text item with the same states as glyphs. Click for Restart Relay, a state-following Stop/Start toggle (`wonda relay disable`/`enable`, never `relay stop`), Open Log (macOS only; the Windows task runs the relay with no log file), and Show/Hide per running WAB; the tooltip carries the full status sentence. The bottom item "Quit Wonda" runs `wonda app quit` (stop relay + disable autostart + remove every open-at-login mechanism (macOS login item, Windows Startup entry) + remove the icon; quit stays quit until the app or `wonda app open` runs again). The Windows tray is a PowerShell/WinForms NotifyIcon consuming `relay health --json` (state) plus a periodic `wab status --json` (the persona Show/Hide list) and shelling wonda verbs, zero platform logic in the script. --stop removes only the icon and leaves the relay running
# macOS Dock menu: right-click a running WAB's Dock tile (the 🐱) for "Show on screen" / "Send to background" (same as wab show/hide). Each running persona has its own Dock tile and its menu controls only that persona. Opt out with WAB_DOCK_MENU=0.
# macOS: a background WAB no longer steals focus or flashes the menu bar / Dock when it opens a new tab; the Dock tile stays, it just never comes to the foreground until you `wab show` it.
wonda wab status                              # list personas + last activity + browser-context health (a running daemon whose Chromium died shows browser-dead with a restart hint instead of a misleading plain "running")
wonda wab login <account> <linkedin|x|reddit|instagram> # RECOMMENDED for a new persona: open headful window, user logs in, session minted in-WAB (independent + fingerprint-coherent)
wonda wab check <account> <linkedin|x|reddit|instagram> # non-interactive session-alive probe
wonda wab bind <persona> --x <acct> --reddit <acct> --linkedin <acct>  # multi-account power-user path: bind N accounts to ONE persona
wonda wab record <url>                        # anonymous one-shot webm recording (no account, no cookies), see below
wonda wab sync-cookies [account]              # force wab → disk cookie sync now (don't wait for the 10-min timer)
wonda wab logs [account] --tail 100           # tail driver.log (--audit for structured per-command log)
wonda wab errors --tail 20 --since 24h        # tail the cross-persona action-failure log
wonda wab top-failures --since 7d             # rank local WAB failures by platform/action/reason, joined with DOM recovery stats
wonda wab top-failures --platform x --json    # machine-readable local failure ranking
wonda wab bundle-failures list                # recent action failure bundles (one per failed run: screenshot, dom, visible-elements, cookies-summary REDACTED)
wonda wab bundle-failures show <id>           # print manifest + file tree for a bundle (id = unix-ms-ts prefix)
wonda wab bundle-failures ship <id>           # zip to ~/Downloads/wonda-failure-<id>.zip for sharing
wonda wab bundle-failures prune               # remove bundles older than 30d (or --max-per-persona, --all)
# Telemetry: on every wab action failure we report (action, platform, reason, error-string, has_bundle, cli_version) as a wab_action_failed PostHog event so maintainers can spot platform rotations across users. NO bundle contents, NO cookies, NO DOM, NO screenshots leave the user's machine. Opt out: WONDA_TELEMETRY_DISABLED=1. For server-side breakdowns, group `wab_action_failed` by `platform`, `action`, `reason`, and `has_bundle` in PostHog. Locally, `wonda wab top-failures` reads only `~/.wonda/wab/errors.jsonl` and persona-local `dom-recoveries.jsonl`, then shows count, last seen, recovered rate, bundle count, and a sample bundle id.
wonda wab migrate-legacy                      # copy a legacy WAB-driver profile into a persona slot
wonda wab restore <persona> [timestamp]       # restore from an hourly snapshot (--list to enumerate)
wonda wab backup disable                      # opt out of auto-push (on by default; existing cloud backups untouched)
wonda wab backup enable                       # opt back in (auto-push synced cookie JSON to wondercat after every disk sync)
wonda wab backup status                       # show config + remote inventory
wonda wab backup push [account]               # one-shot manual push for all platform bindings
wonda wab backup pull [account]               # guarded restore to ~/.wonda/<platform>-cookies/<account>.json; refuses non-empty local unless --force
wonda wab backup pull [account] --dry-run     # preview restores without writing
wonda wab backup list                         # inventory of cloud backups, including device/provenance metadata when available
wonda wab backup delete <plat> <persona> [acct] # remove one backup
wonda wab cookies list                        # explicit cookie backup inventory, metadata only
wonda wab cookies status [account]            # local cookie files plus cloud backup rows
wonda wab cookies port <plat> <persona> [acct] --from-device <id|label> # safely port one selected cloud row to this machine
wonda wab config set <persona> <key> <value>  # persist per-persona spawn defaults (idle-timeout, locale, visible, interactive, proxy_url, timezone, geo_lat/lon)
wonda wab config get <persona>                # print a persona's persisted config

让 cron 角色保持运行。 持续为仅依赖 Cookie 的读取 cron 提供支持的角色,可以运行 wonda wab config set <persona> idle-timeout off,然后运行 wonda wab start <persona>。此后 WAB 会持续运行,现有的 10 分钟 Cookie 同步也会让扁平文件保持最新状态。仅对支持 cron 的角色使用常驻模式;运行 wonda wab config unset <persona> idle-timeout 可恢复默认的 30 分钟空闲关闭设置。

本地浏览器代理(proxy_url)。 默认情况下,本地 WAB 会直接连接(使用你自己的 IP)。运行 wonda wab config set <persona> proxy_url managed,即可让本地浏览器通过你账号创建的孪生代理路由,从而与云端孪生共享相同的出口(适用于保持 IP 连续性,或使用 VPN、办公室网络或 CGNAT 网络)。也可以改用字面值 socks5://…/https://… 手动指定代理;取消设置后会恢复为直接连接。代理是可选的:如果环境禁用了代理创建或代理不可用,浏览器会回退到直接连接。

生命周期命令接受 --account(例如 wonda wab login <account> linkedin);角色会根据账号名自动推导。wonda wab bind 是唯一需要显式指定角色名的命令:当一个 Chromium 需要托管不同平台上名称各异的账号时使用它。

驱动任意页面(snapshot,通过 @ref 操作,再次 snapshot)。 无需操作脚本,即可在角色已登录的 WAB 中于后台点击、输入、滚动并读取任意网站。平台命令未覆盖的任何网站或步骤都可以用它处理;切勿通过计算机操作工具或屏幕点击来驱动 WAB。操作流程:

  1. wonda wab goto <url> --persona <p>(或从标签页当前显示的页面开始)。
  2. wonda wab snapshot -i --persona <p> 会以 YAML 格式输出可交互元素,每行一个,并附带一个 ref:
    # url: https://news.ycombinator.com/
    # title: Hacker News
    - link "new" [ref=e7]:
      - /url: newest
    - textbox "Search" [ref=e41]
    
  3. 对 ref 执行操作:wonda wab click @e7、wonda wab type @e41 "rust" --submit。
  4. 再次生成快照。每次生成快照以及标签页导航后,ref 都会失效;过期的 ref 会立即报错 ref_not_found,并提示重新生成快照。在任何会更改页面的操作(click、type、fill、press、hover、select、scroll、goto、back、forward、reload、upload)中添加 --snapshot,即可在同一次调用中输出最新的交互式快照。

目标语法(一个参数;包含空格时请加引号):@e5 / e5 / ref=e5(快照 ref;在框架内使用 @f1e3)、label=Email、placeholder=Search、640,360(视口坐标 x,y;仅适用于 click 和 hover),其他内容均作为 Playwright 选择器('text=Sign in'、'role=button[name="Post"]'、CSS、xpath=//a)。优先使用 ref。

wonda wab snapshot [-i] [--max-chars N]                  # YAML accessibility tree; -i = actionable elements only (default cut 40000 chars)
wonda wab click <target> [--button left|right|middle] [--double]   # human mouse path; scrolls off-screen elements into view first
wonda wab type <target> <text> [--clear] [--submit]      # clicks the field, human keystrokes; --submit presses Enter after
wonda wab fill <target> <text>                           # instant value set, replaces content ("" clears)
wonda wab press <key> [--target <target>]                # Enter, Tab, Escape, ArrowDown, PageDown, ControlOrMeta+A (lowercase ok)
wonda wab hover <target>                                 # open hover menus / tooltips
wonda wab select <target> <value> [value...]             # native <select>, by option value or label
wonda wab scroll [up|down|left|right] [pixels]           # mouse wheel, default down 600; prints scrollY/scrollHeight/atBottom
wonda wab scroll --to top|bottom                         # or --into <target> to bring an element into view
wonda wab wait <target> [--state visible|hidden|attached|detached] [--timeout 10s]
wonda wab wait --url <substring|glob> | --load load|domcontentloaded|networkidle | --time 2s   # exactly one condition; --timeout max 60s
wonda wab get text|html|value|attr|url|title|box [target] [--attr NAME] [--max-chars N]   # text/html with no target = whole page; box prints {x,y,width,height}
wonda wab eval <js> | --file <path> | - [--main-world]   # prints the JSON result; function expressions are called, promises awaited
wonda wab goto <url> [--wait-until load|domcontentloaded|networkidle]   # offscreen navigation; http(s) only; bare host gets https://
wonda wab back | forward | reload                         # reload also takes --wait-until
wonda wab upload <target> <file> [file...] [--via-chooser]   # file input without a native picker; --via-chooser clicks a button that opens one
wonda wab tabs [list] | tabs open <tab> [url] | tabs close <tab>
wonda wab screenshot --persona <p> [--target <target>] [--output shot.png]   # look at the page, or crop to one element

每个页面命令都接受 --persona(默认值:已配置的默认账号;如果此 persona 在本机上不存在,则报错,绝不会创建全新的空白配置文件)和 --tab(默认值为 default,这是 wonda wab start --open 和 MCP wab_open 显示的共享标签页;任何其他名称都会在首次使用时创建,因此 --tab research 可以让辅助操作远离用户正在查看的页面)。即使输出被管道传递,每个操作也只输出一行简短的纯文本(clicked @e5 (url: ...));snapshot 输出 YAML,get 输出原始值,eval 输出 JSON。--json 会将驱动程序响应输出为一行 JSON(例如 {"ok":"click","url":...});搭配 --snapshot 时,还会包含 snapshot 字段。错误会输出到 stderr,退出码为 1,通常还会有一行 Hint:,指出下一步操作。以 - 开头的文本要放在 -- 后面:wonda wab type @e4 -- "-5 degrees"。

  • type 与 fill: type 会以类似真人的时间间隔逐个输入按键,因此在网站会监控输入的场景下都应使用它(带自动补全的搜索框、发帖和聊天输入框、登录表单)。fill 会立即设置值;长文本的普通表单字段适合使用它。两者都不会提交:使用 type 时添加 --submit,或运行 wonda wab press Enter。
  • eval 默认在隔离环境中运行(能读取 DOM,但看不到页面的 JS 全局变量,对网站不可见);--main-world 会读取页面全局变量,但可被检测到。结果必须是 JSON。读取内容时优先使用 snapshot/get。
  • goto 会先将已存储的 LinkedIn/X/Reddit/Instagram 会话注入全新配置文件;遇到 session_revoked、rate_limited 或 stale_cookies 时会向 stderr 发出警告(但不会失败);遇到验证码或页面始终无法加载时则退出码为 1。跳转到这些平台的页面变更命令会像其他 WAB 操作一样,将更新后的 cookie 写入磁盘。
  • 平台写入操作(发帖、发送私信、建立联系)仍应通过平台命令执行,这些命令带有收件人保护、速率限制和审计日志。其余操作都使用页面命令。

像真人一样滚动页面(browse)。 wonda wab browse [url] --persona <persona> 会在该 persona 的 WAB 中加载页面并滚动:先停下来查看页面,然后滚动、暂停、再滚动,重复 --scrolls 次(默认值为 5)。--scrolls 接受 1–200;超出范围的值会直接报错,不会被限制到范围内,并且会在启动浏览器前拒绝。--first-wait(默认值为 10s)是首次滚动前的暂停时间;--wait(默认值为 5s)是两次滚动之间的暂停时间;两者都会随机浮动 +/-30%,因为间隔过于精确且重复本身就是一种指纹。两者的最短时长均为 250ms,因此很小的值不会因随机浮动而降至零——--first-wait 0 --wait 0 仍会在每次等待时暂停约 250ms,而不是 0;因此使用 --scrolls 200 时,仅这一最短时长就会累计到约 50s。它只会滚动,不会点击或进行互动,因此适用于任何网站。

进度根据实际发生滚动的元素来衡量:网站有占满视口的溢出容器时使用该容器(LinkedIn 的动态位于 <main id="workspace"> 中,此时 window.scrollY 始终不会变化);否则使用文档滚动器。如果连续 2 次滚动后该元素都不再移动,则提前停止,并在打印的摘要中显示 (reached bottom),避免在短页面底部反复滚动。无限动态会持续滚动完整个 --scrolls 次。 --persona 会像其他 wonda wab 命令一样回退到已配置的默认账户;无效的 persona 名称会立即被拒绝,而不是悄悄创建一个空的未登录配置文件。指定 url 时,browse 会在自己的隔离标签页中导航(与其他所有 WAB 写入操作一样),并报告实际浏览的页面(包括任何重定向后的页面)。省略 url 时,则会操作该 persona 共享的默认标签页——即驱动程序的初始页面,也是 wonda wab show/hide 所引用的同一个标签页 ID——滚动该标签页当前显示的内容。wonda wab login 不会在该标签页中留下任何内容:它会打开并导航到自己单独的 <platform>-login 标签页,因此刚刚登录的 persona 仍有一个未被触碰的默认标签页(通常仍为 about:blank)。wonda wab show/hide 也不会导航默认标签页——它们只会切换窗口在屏幕上显示或隐藏,因此两者都不会在该标签页中“打开页面”。会在默认标签页中留下页面的,实际上是直接在该标签页中导航的操作,例如 wonda wab start --open <platform|url>(MCP 的 wab_open 工具也会调用此命令)。这并不是继续浏览之前某次 wonda wab browse <url> 运行所打开页面的方式:那次运行是在自己的隔离标签页中导航,而不带 url 的形式无法访问该标签页。如果默认标签页没有打开任何页面(about:blank)——这是登录新 persona 后的常见情况,因为登录使用的是单独的标签页——命令会失败并要求提供 url,而不是报告成功滚动了空白页面。

browse 输出的是纯文本摘要,而不是 JSON,因此全局标志 --json / --fields / --jq 不适用于它。

wonda wab browse https://example.com --persona <persona> --scrolls 6
wonda wab browse --persona <persona>                      # scroll the shared default tab's current page, no navigation

匿名 PNG 捕获(screenshot)。 wonda wab screenshot 提供兼容性得以保留的 persona 模式,以及新增的匿名 URL 模式。

wonda wab screenshot [persona] 仍会捕获 persona 已打开的标签页,而不会显示窗口。现有标志的含义保持不变:--tab 选择标签页,--full-page 捕获可滚动页面,--output 写入文件。使用 --json 且未指定输出文件时,它仍会返回 {path, base64, mimeType},因此 MCP 和现有自动化收到的内嵌 PNG 保持不变。--persona <name> 可代替位置参数(与每个页面命令都接受的标志相同),--target <target> 则按照页面命令的目标语法裁剪单个元素(wab snapshot 中的 @e12、label=... 或选择器);--target 与 --full-page 不能同时使用。

绝对 http:// 或 https:// 参数会启用匿名模式。该模式会启动一个全新的临时 Chromium,不使用 persona、Cookie 或持久化状态:

wonda wab screenshot \
  'http://127.0.0.1:8765/hero-lab.html#close-colorflight' \
  --output tmp/close-proof.png \
  --viewport 2048x982 \
  --scale 1 \
  --wait-until networkidle \
  --wait-for '#hero-preview' \
  --delay 700ms \
  --animations disabled

匿名模式的默认值为 --viewport 1280x720、--scale 1、--wait-until networkidle、--delay 0 和 --animations allow。--wait-until 接受 load、domcontentloaded 或 networkidle。Wonda 会自动等待 document.fonts.ready;--wait-for <selector> 会等待元素变为可见,--delay <duration> 则会在最后额外等待一段时间以确保页面稳定。--inject-js <file> 会在导航后以异步 IIFE 的形式运行,因此顶层 await 可以正常使用。

要实现确定性的动画效果,可使用 --animations disabled 在捕获时结束有限动画并取消无限动画,或使用 --freeze-at 800ms 将 Web Animations 快进到确切的时间轴偏移并暂停。两个选项不能同时使用。--selector '.hero-stage' 会捕获第一个匹配的元素。--clip x,y,width,height 会捕获 CSS 像素坐标系中精确的文档坐标矩形。该矩形可以超出视口,但必须位于渲染页面范围内。--selector、--clip 和 --full-page 是互斥的捕获模式。

传入多个绝对 URL 可捕获所有 URL。也可以在一个绝对基础 URL 后传入相对路径、查询字符串或带引号的 hash 参数;只要存在相对目标,第一个 URL 就仅作为解析基础,不会单独捕获。添加 --viewports 可使用视口矩阵。整个批次只会启动一次 Chromium:

wonda wab screenshot http://127.0.0.1:8765/hero-lab.html \
  '#fast-close' '#close-colorflight' \
  --viewports 2048x982,1440x1000,390x844 \
  --output tmp/qa \
  --output-template '{route}-{viewport}.png'

对于单次捕获且未使用 --output-template 的情况,--output 是 PNG 文件路径。对于批量捕获、清单捕获或任何使用模板的捕获,它是输出目录。--output-template 支持 {index}、{route} 和 {viewport},展开后的路径必须唯一。{route} 会经过清理;展开后过长的路径组件会缩短,并附加稳定的哈希后缀。--viewport 和 --viewports 不能同时使用。未指定输出标志时,单个 URL 会在当前目录写入 screenshot-<timestamp>.png,批量捕获则会写入 screenshots-<timestamp>/。未指定 --output 的模板相对于当前目录;如果模板来自清单,则相对于清单所在目录。

严格的 JSON 清单可描述同一矩阵:

{
  "url": "http://127.0.0.1:8765/hero-lab.html",
  "routes": ["#fast-close", "#close-colorflight"],
  "viewports": ["2048x982", "1440x1000", "390x844"],
  "scale": 1,
  "waitUntil": "networkidle",
  "waitFor": "#hero-preview",
  "delay": "700ms",
  "injectJs": "scripts/visual-state.mjs",
  "animations": "disabled",
  "outputTemplate": "{route}-{viewport}.png"
}

使用 wonda wab screenshot --manifest visual-qa.json --output tmp/qa 运行。对于互相独立的绝对目标,请使用 urls 而不是 url;routes 则相对于 url 解析。清单键与匿名标量标志对应,并采用驼峰命名,包括 freezeAt、selector、clip 和 fullPage。显式 CLI 标志会覆盖清单值。

匿名 --json 会返回 {ok, captures: [...]},不包含 PNG 字节。每次捕获都会报告 url、finalUrl、viewport、dpr、pageDimensions、consoleErrors、failedRequests 和 fontsLoaded。捕获成功时还会报告 path,表示 PNG 已写入该路径。捕获失败时不会包含 path,而是带有 error,并保留失败前收集的任何诊断信息。某项失败后,浏览器仍会继续处理矩阵中的其余项目;只要有任何捕获失败,进程就会以非零状态退出。请使用此输出进行视觉 QA 诊断。非 JSON 输出只会打印成功生成的 PNG 路径。

匿名视频捕获(record)。 wonda wab record <url> 会在临时 Chromium 中将 URL 录制为 webm(每次调用都会生成新的指纹,不使用 persona,也不使用 cookie)。适用于受 cookie 横幅限制的页面(Notion 公开分享、pdf.js 渲染,以及任何裸用 Playwright 会触发机器人检查的网站)和营销演示录制。

wonda wab record https://example.notion.site/page \
  --output recording.webm \
  --duration 5 \
  --viewport 960x1080 \
  --inject-js scripts/page-script.mjs   # optional: runs after load, before timer starts

# Transcode webm to mp4 at 30 fps (the stealth browser records webm/VP8)
ffmpeg -y -i recording.webm -t 5 -r 30 -an \
  -c:v libx264 -pix_fmt yuv420p -crf 18 recording.mp4

--inject-js 文件会被包装在异步 IIFE 中,因此顶层 await 可正常使用。它会在 domcontentloaded、networkidle 和 400 ms 的绘制稳定等待之后、时长计时器启动之前运行。任何 await 都会占用录制时长。可用于注入深色主题、移除 cookie 横幅、触发滚动动画,以及任何需要在页面上下文中执行的操作。

Node.js 要求:wonda 需要 PATH 中有 Node >= v20。Brew 用户可通过 node 依赖获取;npm 用户默认已有;使用 install.sh 的用户可能需要运行 brew install node(或安装任何 Node 发行版)。如果缺少 Node,wonda wab install 会将私有副本下载到 ~/.wonda/node/。

Cookie 云端备份。 默认启用(可在每台机器上使用 wonda wab backup disable 选择退出)。每次 wab 同步到磁盘后以及正常关闭时,WAB 驱动都会将每个已绑定平台的同步 cookie JSON 推送到 wondercat 后端;未配置 api_key 时,自动推送会直接跳过。若设置了 SOCIAL_COOKIES_KEY,数据会在服务端静态加密(AES-256-GCM);否则会以明文 jsonb 存储。传输载荷始终为明文,因为密钥由服务器持有。list/status/port 命令绝不会打印 cookie 值。

恢复操作受到保护。wonda wab backup pull <account> 和 wonda wab cookies port <platform> <persona> [account] 在未指定 --force 时,如果本地 cookie 文件非空或比远程文件更新,就会拒绝覆盖。强制写入前会先创建隐藏的 .before-pull-* 备份。请使用 --dry-run 检查计划写入内容。如果后端为同一 platform/persona/account 提供多条设备记录,请使用 wonda wab cookies port ... --from-device <id|label> 明确指定来源记录。 当前后端兼容性:旧版服务仍为每个 (account, platform, persona, account_label) 提供一条最后写入生效的记录。新版服务可能会包含 device_id、device_label、source、status、generation 和 provenance;CLI 会在这些字段存在时显示它们,并将旧版记录显示为设备 legacy。

源码位于 cli/wondercat/wab/。驱动程序是 launch.mjs,各平台的操作脚本位于 actions/<platform>/ 下。

如果所选浏览器配置文件没有有效的平台会话 Cookie,WAB 会在读取操作开始前报错。对于 LinkedIn、X、Reddit 和 Instagram,错误信息会包含 wonda wab login <persona> <platform>,而不是只显示难以解释的平台 401/403 错误。此预检为只读;写入操作仍沿用现有错误处理方式,原生登录本身不受影响。

按命令指定传输方式(--via)。 linkedin、x 和 reddit 命令接受:

  • --via cookies|wab:cookies 从每个账号的扁平 JSON 存储读取(速度快;不使用 Chromium);wab 通过账号的 persona Chromium 执行(Cookie 和 TLS 指纹继承自真实浏览器会话)。不支持的值会明确报错,不会静默降级。
  • --via public:仅供明确支持此方式的命令使用的付费公共数据 API。对于 LinkedIn,这会避开已登录 Cookie 和 WAB 配置文件读取,并在 wonda linkedin profile 和 wonda linkedin enrich 中使用公共抓取任务路由。
  • --account <name>:指定要使用的磁盘身份(Cookie 文件名 / persona)。Persona 会自动解析:首次使用 --via wab 时,会自动创建一个以账号名称命名的 persona,并在 TTY 环境下直接接续登录。

读取和写入操作的默认值不同。 读取命令(profile、posts、search、timeline 等)默认使用 cookies(直接 API),因为这种方式速度快且不易触发检测。写入 / 互动命令(post、comment、like、follow、connect、message、mute、repost、delete)默认使用 wab,因为达到一定操作量后,LinkedIn / X / Reddit 的 Cookie API 路径会触发反滥用启发式检测。如果你明确想使用旧版 API 路径(且该命令支持),可以为写入命令传入 --via cookies。

必须使用 --via wab 的命令。 有些命令没有 Cookie 路径,只能通过 Wonda Automation Browser 运行:wonda linkedin comment、wonda linkedin reply-comment、wonda linkedin mute、wonda linkedin follow、wonda linkedin edit-post、wonda linkedin edit-comment、wonda linkedin delete-comment、wonda linkedin post --media、wonda x delete、wonda x reply --attach、wonda x dm send、wonda x dm accept 和 wonda x dm start。这些命令的默认值已经是 wab(stderr 中会有一行提示);显式传入 --via cookies 会报错。Reddit 的写入操作(vote、comment、subscribe、save、unsave、delete 和 subreddit submit)同样只能通过 wab 执行。 运行位置(--engine)。 --via 选择传输方式(浏览器或 Cookie);--engine 选择运行位置,两者相互独立。可选值:local(此计算机上的 WAB)、cloud(账户的云端孪生体,通过孪生体操作 API 访问;控制会话预热过程隐藏在阻塞式等待之后),或 auto(默认值)。当身份存在于此计算机上时,auto 会解析为 local;当身份仅以云端孪生体的形式存在时,则解析为 cloud(即没有本地痕迹的 persona,或通过 wonda twin provision 缓存为 home=cloud 的 persona)。因此,wonda linkedin posts <profile> --account <twin> --engine cloud --via wab 会通过云端孪生体的浏览器返回近期帖子,结果结构与本地命令相同。--via 在两种引擎上的工作方式相同:读取操作默认使用 cookies,写入操作默认使用 wab,并保留显式指定且受支持的覆盖值。已接入 LinkedIn(posts、connect、like/unlike、comment、reply-comment、edit-comment、send-message、follow、mute、delete-post、edit-post)、X(like/unlike、bookmark、retweet/unretweet、follow/unfollow、delete)、Reddit(vote、subscribe、save/unsave、delete)和 Instagram(comment);其他动词仅在本地运行。--engine 可在平台级别指定(因此 linkedin --engine cloud posts 和 linkedin posts --engine cloud 均可运行),但只有已接入的动词会使用该参数;将其传给其他读取操作或尚未接入的写入操作会明确报错,而不会静默忽略。wonda twin run-action 已弃用,现推荐使用 <platform> <verb> --engine cloud(该命令仍可用,以免正在运行的 Agent 出现故障)。在云端,like 支持普通点赞和表情回应(--reaction,会路由到 react 操作);目前只有评论回应(--comment)仍在本地运行。当 persona 没有本地痕迹且没有云端孪生体时,auto 会解析为 local(因此首次使用时自动创建仍可正常工作);若存在云端孪生体,则会解析为 cloud。显式指定 --engine cloud 时,始终在云端孪生体上运行,绝不会回退到实时本地中继。

每个账户的凭据。 Cookie 存储在磁盘上的每账户 JSON 文件中:

  • ~/.wonda/x-cookies/<account>.json
  • ~/.wonda/reddit-cookies/<account>.json
  • ~/.wonda/linkedin-cookies/<account>.json(从旧版单文件格式自动迁移)

每个文件都是由会话持有的本地缓存,不是可移植凭据。一个平台账户可以在多台计算机和云端 Twin 上拥有独立会话。文件会记录所属设备/persona 的 WAB 会话,每次注入、覆盖、仅读取 Cookie、刷新和从备份恢复时,都会先核验该身份。CLI 不会将这些 Cookie 上传到旧版共享托管令牌存储,也不会从中下载 Cookie。--force 绝不会绕过会话不匹配检查。

传入 --account <name> 给 auth set,即可在当前设备上并行保留多个登录状态。即使省略 --persona,绑定关系也会记录在解析后的账户 persona 对应的 account-bindings.json 中;如果匹配的 persona 的 Chromium 正在运行,轮换后的 Cookie 会推送到该实时上下文。切勿使用 auth set 从其他设备或 Twin 复制 Cookie。原生 wab login 更安全。驱动程序还会每隔 10 分钟(以及在正常关闭时)将 Cookie 同步回磁盘,因此轮换后的 Cookie(ct0 轮换、token_v2 服务端刷新等)会自动写回 Cookie 路径,无需手动重新粘贴。直接的 X Cookie 请求也会将响应中的 Cookie 轮换结果合并到同一存储中,并发送完整的已存储 Cookie 集,以便在读取期间保留设备信任 Cookie。 云端 Twin 是其自身稳定且始终在线的会话。常规配置不会从本地 Cookie 文件为 LinkedIn 注入 Cookie;请使用 wonda twin login <persona> --platform linkedin 在 Twin 内登录。云端备份仅用于恢复其来源会话。使用 wonda wab cookies status [persona] 查看本地和云端的归属信息;它不会打印 Cookie 值。近期 LinkedIn 帖子有直接的结构化云端路径:wonda linkedin posts <profile> --persona <persona> --engine cloud --via wab。其他尚未接入引擎的读取操作,可在 Twin 内运行 wonda twin run-now <persona> --command "<platform read command>";使用 run-now 返回的 ID,通过 wonda twin output <twinRunId> 获取捕获的结果。这两种路径都不会将 Twin Cookie 下载到本地。

安全刷新 LinkedIn 的扁平 Cookie 文件。 在执行仅依赖 Cookie 的读取批次前,运行 wonda linkedin auth refresh --account <account> --persona <persona>。磁盘上的 Cookie 较新时,会快速在本地直接无操作。Cookie 过期或即将过期时,会启动一次 WAB(若已在运行则不操作)、执行一次 WAB 到磁盘的同步,并检查本地/WAB 端的 LinkedIn 会话。刷新流程不会调用原始的 wonda linkedin auth check 探测命令,也不会重试凭据。如果 WAB 会话失效,命令会以非零状态码退出,并提示 native re-login required;请停止批次,并通过 wonda wab login <persona> linkedin 手动恢复。

wonda linkedin auth refresh --json 返回 {fresh, refreshed, ageSeconds, expiresAt, sessionAlive}。fresh 表示最终的磁盘状态;只有运行了 WAB 到磁盘同步时,refreshed 才为 true;ageSeconds 是磁盘 Cookie 的存放时长;expiresAt 是已知的过期时间,否则为 null;sessionAlive 是本地/WAB 端的登录检查结果。若本地 Cookie 较新且无需检查 WAB,sessionAlive 为 null。--fresh-within 同时更改可接受的磁盘 Cookie 最大存放时长,以及记录的 li_at 剩余有效期下限(默认为 15 分钟)。即使启用了 JSON 输出,也应将非零退出状态视为权威结果。

使用 Cookie 的 LinkedIn 读取操作可在 --via cookies 的同时选择性启用 --freshen。仅当磁盘 Cookie 已过期时,它才会执行相同的本地预检,然后尝试读取一次。默认行为保持不变:不启用 --freshen 时,--via cookies 仍然快速且不启动浏览器。

安全刷新 X 的扁平 Cookie 文件。 wonda x auth refresh --account <account> --persona <persona> 使用相同的本地优先生命周期,但采用 X 专属的新鲜度规则。由于 auth_token 没有可在本地读取的过期声明,新鲜度仅依据 Cookie 存储时长判断。存储时间不超过 --fresh-within(默认为 15 分钟)时,会在不启动浏览器的情况下直接无操作。存储内容过期时,如果所选 WAB 尚未运行,就会启动它;随后将 X Cookie 同步到磁盘,并检查 WAB 端会话,且不会调用原始的 x auth check 探测命令。会话失效时,命令会以非零状态码退出,并显示准确的原生登录命令。

wonda x auth refresh --json 返回 {fresh, refreshed, ageSeconds, sessionAlive}。使用 Cookie 的 X 读取操作可选择性启用 --freshen;仅当所选磁盘存储已过期时,它才会执行相同的刷新,将读取操作固定到已刷新的账号,并且不会应用于 WAB 读取、写入或身份验证命令。

使用 wonda x auth status --account <name> 查看纯本地信息,包括 Cookie 来源、最近一次捕获的来源记录、代数、归属信息、Cookie 名称,以及缺少设备信任 Cookie 的风险。它不会联系 X,也不会打印 Cookie 值。使用 wonda x browser-bootstrap --account <name>,可显式将所选已存储的 Cookie 包推送到绑定该账号且正在运行的 WAB persona。

操作速率限制

每条平台命令(linkedin、x、reddit、instagram),无论是读取还是写入,都会经过按个人资料划分的速率限制保护,以免突发操作触发平台的影子封禁/反滥用启发式规则。用量按 (platform, account) 统计,采用滚动 24 小时窗口,并按个人资料记录在 ~/.wonda/wab/personas/<persona>/ 下(因此,云端副本的限额会在多次运行间保留)。

  • 读取会_限速_,但不会被阻止:操作间隔会加入抖动,使个人资料的读取速率低于 read_per_min(默认 75 次/分钟),并且在不同命令调用之间持续生效。

  • 写入会按每日分桶上限进行检查。以下为 LinkedIn 默认值(其他平台会跟踪用量并计入每日总量,但默认没有按类型划分的写入上限):

    分桶命令安全值最大值
    联系拓展connect + send-message + inmail2040
    帖子post35
    评论comment、reply-comment1020
    互动like2550
    访问visit1530
    搜索search、search-posts2550
    总计(所有非读取操作)以上任意命令达到 90% 时警告100

salesnav search(Sales Navigator)不受限制:它没有商业用途限制,因此会像不限量读取一样限速,而不会计入 search 上限或每日总量。

默认情况下,上限是软限制:超出安全值/最大值的操作会向 stderr 输出影子封禁风险警告,但仍会继续执行。传入 --hard(或在配置中设置 mode: hard)后,超限写入将改为中止(退出码为 1)。

wonda actions 是一个 JSON 数据查询(不是仪表板),可按需读取个人资料在滚动 24 小时内相对于上限的用量;实时钩子始终会静默运行上限检查/限速/警告。

wonda actions                        # rolling-24h usage per profile vs caps, as JSON
wonda actions --persona <persona>        # one profile
wonda actions --platform linkedin    # filter to one platform
wonda linkedin quota                 # planning view: remaining LinkedIn allowance per bucket (used vs safe/max + remaining, incl. untouched buckets) BEFORE a big pull, instead of hitting the mid-output warnings
wonda actions sync                   # flush local action/health events to your Wonda account
wonda actions sync --persona <persona>   # flush one profile's ledgers
wonda linkedin post "…" --hard       # enforce caps as hard limits for this command

配置 API 密钥后,本地账本(操作日志、WAB 审计/错误日志、Cookie 来源记录)也会在每条命令执行时自动在后台同步到你的 Wonda 账户健康记录:采用尽力而为、批量处理且具备幂等性(每条记录都有稳定的客户端事件 ID,因此重试不会重复计数),离线使用仍可正常运行,同步会在之后补上。wonda actions sync 会强制完整刷新,并打印服务器的插入/去重计数;未配置 API 密钥时则会静默地不执行任何操作。仅会传输事件元数据,不会传输 Cookie 值或故障数据包。设置 WONDA_TELEMETRY_DISABLED=1 可关闭后台同步。

通过 ~/.wonda/config.json 中的 action_limits 覆盖/禁用/启用硬模式(上限会限制在安全下限/上限范围内,因此覆盖设置可以放宽限制,但不能在不知情的情况下禁用保护):

{
  "action_limits": {
    "mode": "hard",
    "read_per_min": 75,
    "total_per_day": 100,
    "buckets": { "linkedin": { "outreach": { "safe": 15, "max": 30 } } }
  }
}
配置键

wonda config get|set|list 键:

  • api-key:你的 wondercat API 密钥。
  • base-url:API 基础 URL(默认为生产环境;设置为 https://staging.api.wondercat.ai 可用于预发布环境)。
  • default-account:平台命令未传入 --account 时使用的账户。
  • wab-backup-enabled:用于 Cookie 云备份的 true/false(与 wonda wab backup enable/disable 相同)。默认开启;只有显式设为 false 才会禁用。

Transport 不是配置键。每条命令会按操作类型选择传输方式(读取默认使用 cookies,写入/互动默认使用 wab),所有平台均一致。可通过 --via cookies|wab 按命令覆盖(平台支持时)。

如何看待内容创作

你是一位拥有完整制作工具包的营销总监。在使用任何工具之前,请先思考:

  1. 是什么产品类别?(美妆、食品、科技、时尚、健身等)
  2. 这种类别适合什么形式?(日常用品适合 UGC 梗图,奢侈品适合电影感风格,转变类内容适合前后对比,服务适合客户评价)
  3. 吸引点是什么?(引发共鸣的情境、令人惊讶的反转、令人向往的生活方式、社会认同)
  4. 具体场景是什么?(不是“产品放在桌上”,而是“某人在有趣的情境中发现产品”)

决策流程

收到内容创作请求时,请按以下顺序执行:

第 1 步:收集背景信息
wonda brand                                                    # Active brand: identity, colors, fonts, logos, products
wonda brand list                                               # All brands owned by this account/org
wonda brand show <brand-id>                                    # Specific brand
wonda brand extract https://stripe.com                         # Local-only: writes ./output/stripe.com/{DESIGN.md, tokens.json, assets/}
wonda brand extract https://stripe.com --save --make-active    # Local + persist + activate (the common path)
wonda brand extract https://stripe.com --save --name "Stripe"  # Persist with a custom name
wonda brand extract https://stripe.com --no-output --save      # Don't write to disk, persist only
wonda brand save                                               # Persist the most recent ./output/<domain>/ dir to the server
wonda brand save --from ./output/stripe.com --make-active
wonda brand pull <brand-id>                                    # Download a saved brand back to ./output/<domain>/
wonda brand activate <brand-id>                                # Set as the active brand
wonda brand upload-logo <brand-id> https://acme.com/logo.svg   # Attach a logo by URL (--variant wordmark|icon|dark|light)
wonda brand upload-font <brand-id> https://acme.com/Geist.woff2 --weight 700
wonda brand delete <brand-id>
wonda analytics instagram                                      # What content performs well
wonda scrape social --handle @competitor --platform instagram --wait  # Competitive research (if relevant)

# Cross-platform research (if relevant)
wonda x search "topic OR keyword"                              # Find conversations on X/Twitter
wonda x user-tweets @competitor                                # Competitor's recent tweets
wonda reddit search "topic" --sort top --time week             # Reddit discussions
wonda reddit feed marketing --sort hot                         # Subreddit trends
wonda linkedin search "topic" --type COMPANIES                 # LinkedIn company/people research
wonda linkedin profile competitor-vanity-name                  # LinkedIn profile intel
第 2 步:查看内容技能

内容技能是针对常见内容类型的分步指南。每项技能都会准确说明要使用哪些模型、提示词和编辑操作,以及使用顺序。从头开始制作前,务必先查看技能。

技能托管在服务端、按账户区分且可编辑(与 wonda brand save 的模式相同)——你不会下载一份归自己所有的 .md 文件。Wonda 提供一套规范的默认技能,作为只读后备方案提供。执行任务时,实时获取这些技能;想要调整时,可将默认技能分叉为自己的副本;Wonda 会保留完整的版本历史。skill list 会显示你当前生效的技能(默认技能与个人修改叠加后的结果),并标记默认版本后来有所变更的分叉技能。

wonda skill list                                # Browse your effective skills (defaults + your own); forks with a changed default are flagged
wonda skill get <slug>                          # Pull a skill's full step-by-step guide live to stdout

默认技能目录(实时来源:wonda skill list,同时会显示你自己的分叉版本和修改,并标记偏离情况):

视频

别名功能
product-demo-video高级约 15 秒多节拍产品演示:开发者遇到痛点,运行你的工具,工具在屏幕上执行真实操作,展示效果,最后呈现品牌 CTA。整个视频由一个 HTML 合成画面构建,逐帧捕获后再用 ffmpeg 混流
product-video根据图像或从头开始制作产品/场景视频
split-screen-demo5 秒 16:9 LinkedIn 循环视频,对比源文档与设计好的幻灯片,最后呈现划掉竞争对手的 CTA
tiktok-ugc-pipeline逆向分析爆红短视频,生成 5 个变体并自动发布
ugc-dance-motion根据图像和参考素材制作舞蹈与动作迁移视频
ugc-hook-brainstorm25 个经过评分、能吸引用户停下滑动的 UGC 开场钩子,热门演员阵容、iPhone 16 美学风格、心理驱动因素
ugc-reaction-batch批量制作 TikTok 原生风格的 UGC 反应视频
ugc-talking对镜口播 UGC 广告,可采用单片段、双角度画中画或 20 秒以上长视频形式

图像

Slug功能
creative-static-ads高转化单帧静态广告、6 个转化支柱、8 种格式原型、8 种心理钩子
linkedin-media-premium-generation制作一张让人停下滚动的 LinkedIn 主视觉卡片(1920x1080),采用分层视觉语言:斜体衬线标题、真实产品截图、纸张颗粒质感、悬浮式社交证明卡片。六种布局模式共享相同的视觉基因。通过 Wonda CLI 从 X / LinkedIn / Reddit 获取真实引言。
premium-static-ads使用 HTML+Playwright 制作像素级精准的静态广告,并提取品牌信息(wonda brand extract)。真实字体、精确设计令牌、可复现模板
tiktok-slideshow-carousel3-5 页 TikTok 轮播,呈现自然风格,同时推广你的产品,包含钩子、衔接、揭示

社交调研

Slug功能
analyze-reel分析热门 Reel 或 TikTok,拆解其走红原因,并提供 5 个改编后的内容创意
linkedin-account-multithreading-map梳理已接受名单中各账户的当前覆盖情况、关系状态,以及平台建议的引荐路径
linkedin-buying-committee-radar监控指定账户的新职位匹配、职位变动、近期帖子和 Sales Navigator 提醒
linkedin-comment-first-opportunities找出一些正在进行的 LinkedIn 对话,供用户发表具体、有用的公开评论
linkedin-competitor-engager-watch追踪指定的 LinkedIn 用户,仅将他们新近的高信号互动者整理为符合条件的外联名单
linkedin-engager-intel获取 LinkedIn 帖子的所有评论者和反应者及其个人资料 URL,用于温暖外联
linkedin-icp-angle-brief将 LinkedIn 个人资料转化为可解释的 ICP 判断,以及一个有证据支撑的外联切入点
linkedin-icp-qualify补充 LinkedIn 互动者当前雇主的信息(行业、员工人数、总部、简介),以便筛选 ICP 匹配度
linkedin-inbound-intent-triage将新的 LinkedIn 通知、邀请、消息和自有帖子评论整理为有证据支持的响应队列
linkedin-social-listening将针对具体痛点、迁移和购买意向措辞的搜索结果转化为按优先级排序、有证据支持的 LinkedIn 候选名单
reddit-subreddit-intel抓取热门帖子、分析传播规律并生成帖子创意
twitter-influencer-search为产品发布寻找微型影响者和扩散者

策略

Slug功能
linkedin-post-system将原始创意转化为符合成熟格式且贴合用户确切语气的 LinkedIn 帖子。通过 wonda linkedin profile/posts 初始化用户的语气语料库,将创意映射到 28 种成熟内容格式之一,使用防 AI 垃圾内容护栏起草 2 个版本。
marketing-brain用于构思吸引点、视觉内容、广告和竞争分析的策略大脑

实用工具

Slug功能
extract-apply-style从任意图像中提取视觉风格,然后以该风格生成新主体
ffmpeg本地确定性媒体转换:剪辑、替换音频、烧录字幕、适配社交媒体格式、拆分场景、剪除静音、提取帧、生成分析产物
image-edit编辑现有图像、图生图、移除背景、裁剪、叠加文本、矢量化
slide-generation从任意内容源、代码库、Notion 笔记或 Google Docs 生成品牌风格的幻灯片
software-ui-mockups根据程序的真实数据源,以像素级精度在 HTML 中渲染真实的软件界面、终端/CLI TUI、Chrome 浏览器窗口和 macOS 桌面,用于演示视频、幻灯片、截图和文档
tiktok-caption-presets通过 wonda edit --preset 应用 TikTok 风格的 textOverlay 和 animatedCaptions 预设

编辑技能(可选)。 如果默认设置不太合适,可以派生并编辑,而不是绕开它。编辑默认设置会自动将其派生到你的账户中:

wonda skill create my-ugc --from ugc-talking    # Fork a default into your own editable copy
wonda skill edit my-ugc --editor                # Record a new version (opens $EDITOR; or --file <md> / stdin)
wonda skill diff <slug>                          # See what changed in the default since you forked it (drift)
wonda skill refactor <slug> --editor             # Re-base your fork onto the updated default, clears the drift hint

如果有匹配的技能 → wonda skill get <slug>,阅读并根据上下文调整,然后执行每个步骤。

如果没有匹配的技能 → 从头开始构建(步骤 3)。

步骤 2.5:决定是否在本地完成

并非每项媒体任务都应该交由 Wonda 编辑。请遵循以下路由规则:

  • 对于 AI 生成、AI 转录/对齐、抓取、发布、托管式转场,以及需要媒体 ID 或远程任务的工作流,请使用 wonda。
  • 对于已有或可以下载的文件上的确定性转换,请使用本地 ffmpeg:修剪、裁剪/缩放/填充、拼接(合并多个片段)、替换音频、提取音频/帧、反转、规范化以供交付、烧录字幕、分割场景、剪除静音,以及构建分析产物。始终在本地合并片段——一旦任何输入超过约 7MB,服务端合并可能会卡住 30 多分钟。

如果任务从 Wonda 媒体 ID 开始,但实际编辑是确定性的,请先将其转换成本地文件:

wonda media download <mediaId> -o ./input.mp4

进行任何本地 ffmpeg 操作之前:

which ffmpeg
which ffprobe
ffmpeg -version
ffprobe -v error -show_format -show_streams -of json ./input.mp4

本地字幕/文本处理的字体规则:

  • 优先使用明确的字体文件路径,而不是字体族名称。
  • 切勿假设某种字体已存在。请先使用 fc-match、fc-list、/System/Library/Fonts、/Library/Fonts、~/Library/Fonts 或 /usr/share/fonts 检查。
  • 如果任务主要涉及本地后期处理/字幕/格式整理/分割/产物提取,请先查看 ffmpeg 技能,再编写命令。
  • wonda edit video 会为每项编辑器操作在本地运行 ffmpeg:trim、crop、volume、speed、reverseVideo、extractFrame、extractAudio、editAudio、imageCrop、imageToVideo、merge、overlay、splitScreen、splitScenes、skipSilence。渲染会通过 ffmpeg 在你的机器上运行:不会创建服务端 editor_job,渲染本身也不会占用额度(输入会被下载,结果会在渲染前后上传)。textOverlay 和 animatedCaptions 也会在本地通过捆绑的 hyperframes(Chromium)渲染器运行。ffmpeg 必须位于 PATH 中(wonda doctor 会进行验证)。这些操作不再使用公共 API /video/edit、/image/edit、/audio/edit,调用时会返回 410 Gone。
  • **始终在本地合并片段。**一旦任何输入超过约 7MB,服务端合并可能会卡住 30 多分钟;出于同样的原因,wonda edit video --operation merge 现在默认使用本地 ffmpeg 运行。
  • **切勿先为每个片段混入音频再进行拼接。**应先拼接视频轨道,然后在拼接后的完整时间线上叠加一次完整的旁白或音乐轨道。逐片段混入音频会造成剪切点冲突和静音间隙。

除非用户另有要求,默认的本地导出目标:

-c:v libx264 -preset medium -crf 18 -pix_fmt yuv420p -movflags +faststart -c:a aac -b:a 192k

务必将 -y 作为第一个标志传入,这样命令就会自动覆盖输出文件。如果输出路径已存在,ffmpeg 会交互式提示;Agent shell 会一直卡在该提示上,直到超时。

步骤 2.6:选择合适的本地工具

编辑可使用以下四种工具之一。选择第一个匹配需求的条目。

需求工具原因
基本转换(修剪、裁剪、变速、合并、叠加等)wonda edit video --operation <op>封装本地 ffmpeg。免费、结果确定,在你的机器上渲染(不使用服务器渲染,也不消耗额度)。
动态图形、动画文本、字幕条、片头/片尾wonda compose <kind>(hyperframes HTML compositions,本地渲染)一次完成,无需 Lambda,也不会在 wonda 中捆绑 Node。需要 Node >= 22 + ffmpeg。
动态字幕、品牌特效流水线、场景特效wonda transitions run --preset <name>(miruna 的 transitions service)托管服务;特效库更丰富(SAM3 遮罩、场景转场、字幕预设)。
基本工具未涵盖的一次性原始转换通过 Bash 使用原始 ffmpeg(参见 ffmpeg 技能)比选错基本工具更快;适用于“对本地文件进行结果确定的转换”。
复杂的多步骤流水线串联上述工具(wonda edit ... → 原始 ffmpeg → wonda compose ...)每一步都会写入本地 mp4;将其作为 --input / --media 传给下一步。

在新机器上运行一次 wonda doctor,确认 ffmpeg、node 和 hyperframes 均可用。传入 --warm-chrome,预先下载 hyperframes 捆绑的 Chromium(约 150 MB),这样首次剪辑渲染时就不会暂停等待下载。传入 --wab,还可检查磁盘上的 WAB 浏览器运行时(已安装的驱动与此构建版本固定的驱动是否一致、驱动目录清单);离线、只读,且与 --relay 一样仅提供参考。

示例:

基本修剪和合并(wonda edit,本地 ffmpeg):

wonda edit video --operation trim --media $VID \
  --params '{"trimStartMs":3000,"trimEndMs":10000}' \
  --wait -o ./trimmed.mp4

wonda edit video --operation merge --media $A,$B,$C \
  --wait -o ./merged.mp4

动态图形片头(wonda compose,hyperframes):

wonda compose motion --template fade-in \
  --text "Q4 Recap" --subtitle "Wondercat" \
  --duration 4 --resolution portrait -o intro.mp4

wonda compose text --input ./clip.mp4 --text "NEW DROP" \
  --position bottom-center -o overlay.mp4

为成片添加动态字幕(transitions service):

wonda transitions run --media $VID --preset caption_word_pop --wait -o final.mp4

使用原始 ffmpeg 执行基本工具未涵盖的操作(例如,拼接并淡出音频):

ffmpeg -y -f concat -safe 0 -i list.txt \
  -af "afade=out:st=29:d=1" \
  -c:v libx264 -crf 18 -pix_fmt yuv420p \
  -c:a aac -b:a 192k out.mp4

多步骤流水线(制作片头 → 使用 wonda 将片头与主体合并 → 添加 transitions 字幕):

wonda compose motion --template scale-pop --text "Hello" --duration 3 -o intro.mp4
wonda edit video --operation merge --media $(wonda media upload intro.mp4 --quiet),$MAIN_VID \
  --wait -o merged.mp4
MERGED_ID=$(wonda media upload merged.mp4 --quiet)
wonda transitions run --media $MERGED_ID --preset caption_word_pop --wait -o final.mp4
步骤 3:从头构建(链式端点)

没有匹配的技能时,可将各个 CLI 命令串联起来。每一步的输出都会传递给下一步。

单个素材:

wonda generate image --model gpt-image-2 --prompt "..." --aspect-ratio 9:16 --wait -o out.png
# --params '{"quality":"high"}' — auto/low/medium/high (default auto)
# --negative-prompt "..."       — override what to exclude (model-dependent)
# --seed <number>               — pin the seed for reproducible results (model-dependent)
wonda generate video --model seedance-2 --prompt "..." --duration 5 --params '{"quality":"high"}' --wait -o out.mp4
wonda generate text --model <model> --prompt "..." --wait
wonda generate music --model suno-music --prompt "upbeat lo-fi" --wait -o music.mp3

音频(语音、转录、对话):

# List available voices (TTS + dialogue use the same set)
wonda audio voices

# Text-to-speech
wonda audio speech --model elevenlabs-tts --prompt "Your script here" \
  --params '{"voiceId":"hpp4J3VqNfWAUOO0d1Us"}' --wait -o speech.mp3
# elevenlabs-tts always requires a voiceId — pick one from `wonda audio voices`

# Transcribe audio/video to text
wonda audio transcribe --model elevenlabs-stt --attach $MEDIA --wait

# Multi-speaker dialogue (each speaker needs a voiceId from `wonda audio voices`)
wonda audio dialogue --model elevenlabs-dialogue \
  --prompt 'ALICE: Hi! BOB: Hello!' \
  --params '{"speakers":[{"label":"ALICE","voiceId":"hpp4J3VqNfWAUOO0d1Us"},{"label":"BOB","voiceId":"IKne3meq5aSn9XLyUdCD"}]}' \
  --wait -o dialogue.mp3

音频 AI 操作(直接推理,不是编辑器操作):

# Denoise / dereverberate speech
wonda audio enhance --model replicate-resemble-enhance --attach $MEDIA \
  --params '{"denoise":true,"chunkSeconds":10}' --wait -o enhanced.wav

# Split a track into voice and instrumental stems
wonda audio extract-voice --model replicate-demucs --attach $MEDIA \
  --wait -o vocals.wav

为视频添加动态字幕:

animatedCaptions 操作会一步完成所有处理:提取音频、转录并生成词级时间信息,然后将逐词显示的动态字幕渲染到视频上。

# Generate a video with speech audio
VID_JOB=$(wonda generate video --model seedance-2 --prompt "..." --duration 5 --aspect-ratio 9:16 --params '{"quality":"high"}' --wait --quiet)
VID_MEDIA=$(wonda jobs get inference $VID_JOB --jq '.outputs[0].media.mediaId')

# Add animated captions (single step)
wonda edit video --operation animatedCaptions --media $VID_MEDIA \
  --params '{"fontFamily":"TikTok Sans SemiCondensed","position":"bottom-center","sizePercent":80,"strokeWidth":2.5,"fontSizeScale":0.8,"highlightColor":"rgb(252, 61, 61)"}' \
  --wait -o final.mp4

视频原有的音频会保留。不要用 TTS 替换音频——Sora 已经生成了语音。

转场(对单个视频应用效果管线):

wonda transitions presets                            # List built-in presets (JSON)
wonda transitions operations                         # Grouped by category (analysis/effect/...)
wonda transitions operations --json                  # Full per-param metadata
wonda transitions llms                               # Full reference (presets + ops + dependencies)
wonda transitions run --media $VID --preset flash_glow --wait -o out.mp4
# Or send an agent-generated timeline of clips (inline JSON):
wonda transitions run --media $VID \
  --clips '[{"layer_type":"video","start_frame":0,"end_frame":60}]' --wait -o out.mp4
# Or from a file (handy for long agent timelines):
wonda transitions run --media $VID --clips ./timeline.json --wait -o out.mp4
# To attach scene_transitions: pass an envelope (clips + scene_transitions)
# instead of a bare clip array — same file, both fields forwarded.
wonda transitions run --media $VID --clips ./timeline_with_transitions.json --wait -o out.mp4
# where timeline_with_transitions.json is:
#   { "clips": [...],
#     "scene_transitions": [{"name":"crossfade","params":{"duration":8},"boundaries":[60]}] }
wonda transitions job <jobId>                        # Poll a transition job

只能使用 --preset 或 --clips 其中之一。需要完整账户(已登录)。**编写 clips 时间线时,务必先阅读 wonda transitions llms。**其中说明了检测、分段和效果之间的依赖关系,哪些操作需要蒙版,以及完整的片段规范结构(图层类型、轨道、效果、变换)。

**预设变量(variables 块)。**每个预设都会在 wonda transitions presets 的 variables 下声明其接受的模板变量。每个条目都包含 name、description 和 required。必须提供必需变量,否则任务会被拒绝并返回 400——不再静默跳过。使用 --var name=value 传入变量(可重复使用);对于常见的 prompt 情况,也可以使用 --prompt 快捷选项:

# flash_glow_prompted requires { prompt }
wonda transitions run --media $VID --preset flash_glow_prompted \
  --prompt "woman in white dress" --wait -o out.mp4

# text_behind_person requires { prompt, text }
wonda transitions run --media $VID --preset text_behind_person \
  --var prompt="the person" --var text="HELLO WORLD" --wait -o out.mp4

# Numeric-typed vars: bare digits are decoded as numbers, "true"/"false" as
# bools, everything else stays a string. Presets that compare frame indices
# numerically (border_frame, marquee_text, quick_motion_text, bg_remove_scale)
# need this — quoting an int turns it back into a string.
wonda transitions run --media $VID --preset border_frame \
  --var exit_start_frame=200 --var exit_end_frame=251 --wait -o out.mp4

prompt 变量是一个检测文本查询,用于描述要遮罩的主体,并传递给 SAM3 以生成逐帧分割蒙版。它不是用于内容生成的提示词。

要构建需要检测蒙版的自定义 --clips 时间线?添加一个 layer_type: "video" 的片段,并设置 mask: {layer_type: "mask", analysis_steps: [{name: segment, params: {prompt: "..."}}]}。SAM3 会根据提示词一步完成检测和分割,因此不需要单独的 detect 步骤。

在渲染前预热蒙版(推荐)

对于带有 mask:<label> 变量的预设,请先运行 wonda transitions ensure-masks,这样渲染开始时蒙版就已准备就绪。对于一个(媒体,标签)组合,首次调用需要 1-3 分钟;后续调用几乎是即时的。

# 1. Ensure masks are prepared for the labels you'll use, blocking until ready.
wonda transitions ensure-masks --media $VID --labels person,phone --wait

# 2. Run the render. Masks are already prepared.
wonda transitions run --media $VID --preset slide_reflect_background \
  --var "masks=mask:person+phone" --wait -o out.mp4

ensure-masks 标志:

  • --media MEDIA_ID — 必填,蒙版对应的视频
  • --label NAME — 可重复,每次调用指定一个标签(--label person --label phone)
  • --labels NAME,NAME — 逗号分隔的替代写法(--labels person,phone)
  • --wait — 阻塞,直到所有标签都准备就绪
  • --timeout DUR — 设置 --wait 时的最长等待时间(默认 10m)

多提示词语法:--var 中的 mask:woman+phone 会拆分成独立蒙版(woman、phone),并逐帧合并。将每个子标签分别传给 ensure-masks,以便全部预热。

以下情况可跳过 ensure-masks:

  • 非蒙版预设(没有 mask:<label> 变量)——无需准备
  • 之前的渲染已用过这些(媒体,标签)——已准备就绪

以下情况 ensure-masks 最为重要:

  • 首次使用基于蒙版的预设处理新媒体
  • 调整渲染参数——预热一次后,即可随意运行多次,无需重新准备

多场景预设(requiresMultiScene: true)。 某些预设使用场景感知逻辑,需要包含多个剪辑/场景的视频。查看 wonda transitions presets 中的 requiresMultiScene。如果为 true,输入单个连续镜头只会产生一个场景,效果可能不够明显。请先合并片段,或使用具有自然剪辑的视频。

调整预设参数。 每个预设都是剪辑形状。使用 wonda transitions preset <name> --json 获取单个预设,读取其 clips:(单轨)或 tracks:(多轨)字段,编辑任意剪辑参数,然后通过 --clips 提交。对于多轨预设,将每个剪辑的 track 设为其来源轨道对应的索引,以展平数据。如果预设声明了 sceneTransitions:,请在请求中原样传递该数组。

# Single-track preset (e.g. flash_glow_montage): copy clips: directly
wonda transitions preset flash_glow_montage --json | jq '.preset.clips' > clips.json
# edit clips.json
wonda transitions run --media $VID --clips "$(cat clips.json)" --wait -o out.mp4

自动修复安全网(--auto-repair、--face-bbox)。 对于 --clips 渲染,工作进程会在渲染前对提交的 JSON 运行确定性修复流程,默认开启。修复项包括:按宽度适配字体大小、限制字符下伸部分不超出画布底部、对齐堆叠间距(根据大写字母高度公式计算 ROW1_py)、将关键帧边界限制在 [0, source_duration]、修剪同一 y 坐标行上的字幕重叠、延长蒙版时长至完整时长、将描边宽度设为零、按字体对齐字间距目标值、延长蒙版抠像时长、限制负起始值,以及(启用 --face-bbox 时)移动与人脸重叠的字幕。传入 --auto-repair=false 可启用严格验证;此时超出规格的值会作为渲染错误显示。

# Push body captions off the speaker's face. bbox is x1,y1,x2,y2 in canvas pixels (top-left origin).
wonda transitions run --media $VID --clips ./timeline.json \
  --face-bbox 200,160,520,520 --wait -o out.mp4

# Strict mode — disable auto-repair to see exactly which clips fail validation.
wonda transitions run --media $VID --clips ./timeline.json \
  --auto-repair=false --wait -o out.mp4

--face-bbox 只会移动正文字幕。需要显示在说话人后方的装饰文字,仍须通过显式的 mask_cutout {prompt: "person"} 剪辑处理。

不同作业类型的输出 URL 路径不同:

  • 推理作业(生成、音频):.outputs[0].media.url 和 .outputs[0].media.mediaId
  • 编辑器作业(编辑):.outputs[0].url 和 .outputs[0].mediaId

模型瀑布流

图像

默认:gpt-image-2。OpenAI 的旗舰模型——最强的提示词遵循能力、最佳的图像中文字效果,以及通过参考图进行高保真编辑。支持 1-4 张参考图。质量档位:auto(默认)、low、medium、high——通过 --params '{"quality":"high"}' 传入。输出上限为 1536px。

若专门进行图生图编辑(更改、添加/移除、重设风格、移除背景、裁剪、叠加文字、矢量化),请使用 wonda skill get image-edit——它包含完整的编辑专用决策树。

仅在符合以下情况之一时选择其他模型:

  • 用户明确要求使用其他模型
  • 参考图超过 4 张 → nano-banana-2(gpt-image-2 最多支持 4 张参考图;nano-banana-2 最多支持 14 张)。参考图为 1-4 张时,继续使用 gpt-image-2。
  • 需要矢量输出 → runware-vectorize
  • 需要移除背景 → birefnet-bg-removal
  • 需要尽可能低成本/快速出草稿 → z-image
  • 需要高于 1536px/真正的 4K 输出 → nano-banana-pro(1K/2K/4K)或 nano-banana-2(1K/2K/4K)。gpt-image-2 的输出上限为 1536px。
  • gpt-image-2 不可用/OpenAI 服务中断 → nano-banana-2 或 seedream-4-5 或 grok-imagine-pro
视频

默认:seedance-2(时长 5/10/15s,默认 5s,画质:高)。升级选择:

  • 对画质不满意或需要不同风格 → sora2 或 sora2pro
  • Seedance 2 单个片段最长 15s,Sora 最长 20s → 需要更长内容时,通过合并拼接多个片段
  • Veo(veo3_1、veo3_1-fast)可用,但不在默认瀑布流中。仅在用户明确点名要求使用 Veo 时选择。
  • Gemini Omni(gemini-omni-video)可用,但不在默认瀑布流中。仅在用户点名要求使用 Gemini,或明确需要多图参考 T2V/I2V(最多 7 张参考图)或 4K 输出时选择。

图生视频路由(附加参考图时必须遵循):

  • 参考图中可见人物/面部 → 必须使用 kling_3_pro(对面部身份的保留效果更好)
  • 参考图中没有人物 → 使用 seedance-2
  • 文生视频(无参考图): Seedance 2 可以很好地生成角色。此规则仅适用于使用 --attach 附加图片时。

Kling 模型系列:

  • kling_3_pro — 文生视频和图生视频,支持起始/结束图、自定义元素(@Element1、@Element2),时长 3-15s,比例 16:9/9:16/1:1
  • kling_2_6_pro — 通用型,时长 5-10s,比例 16:9/9:16/1:1,支持文生视频和图生视频
  • kling_2_6_motion_control — 动作迁移:需要同时提供参考图和参考视频,根据图片的外观重现视频中的动作
  • kling2_5-pro — 经济型 Kling 选项,时长 5-10s,支持首帧/尾帧图片

Kling 提示词规则(重要): Kling 的提示词字段上限为 2,500 个字符,而且对 Sora 风格的结构化说明(SCENE: / SUBJECT: / MOTION: / BANNED LOOK: 分节标题)响应不佳。使用这种格式时,Kling 会紧抓氛围类名词,却悄然丢弃核心主体(经实测:同一条 2,842 字符的 Sora 风格提示词,在 Sora 2 Pro 和 Seedance 2 上都能正确渲染,但在 Kling 上完全没有生成手机,即使将提示词缩短到 2,250 字符也一样)。从 Seedance 升级到 Kling,或直接使用 Kling 时,请将提示词改写为简短的自然语言描述(约 1,000–1,500 个字符),并在开头的句子中先点明主角主体,不要把它藏在 SUBJECT: 分节中。不要将 Sora 格式的提示词原样传给 Kling。

其他视频模型:

  • grok-imagine-video — xAI 视频生成,时长 5-15s,支持 7 种画面比例,包括 4:3 和 3:2
  • gemini-omni-video:Google Gemini Omni。文生视频和图生视频,最多支持 7 张参考图(槽位 reference_image_1 到 reference_image_7)。时长 4/6/8/10s,画面比例 9:16 和 16:9,分辨率 720p / 1080p / 4K。定价:720p/1080p 为 $0.15 基础费用 + 每秒 $0.075,4K 为 $0.75 基础费用 + 每秒 $0.075。不支持原生音频(如需语音,请搭配单独的音频模型)。
  • topaz-video-upscale — 提升视频分辨率(1-4x 倍率,支持帧率转换)
  • sync-lipsync-v2-pro — 用于用户提供的视频和音频对的旧版口型同步。效果不如原生音频生成,而且几乎从来不是生成新内容的合适选择。规则请参阅“口型同步”部分。

Seedance 系列(默认视频模型,会自动去除水印):

  • seedance-2 — Seedance 2.0 基础版(T2V/I2V,5-15s,high=标准/basic=快速)
  • seedance-2-omni — 多参考素材生成(图片、音频参考)
  • seedance-2-video-edit — 通过文本提示词编辑现有视频

视频时长: 可接受的 --duration 值因模型而异。请使用 wonda capabilities 或 wonda models info <slug> 查询。

音频
  • 音乐:suno-music(如需纯音乐,请设置 --params '{"instrumental":true}')
  • 文本转语音:elevenlabs-tts——仅用于静音画面上明确要求旁白或画外音的场景。不要用它来“让 UGC 角色说话”——Sora / Sora 2 Pro / Veo 3.1 / Kling 3 / Seedance 2 能以任何语言生成原生同步语音,效果远胜于此。始终在参数中设置 voiceId。默认女性声音:--params '{"voiceId":"21m00Tcm4TlvDq8ikWAM"}'(Rachel)。
  • 转录:elevenlabs-stt
  • 多人对话:elevenlabs-dialogue
  • 增强音频(清理嘈杂语音):通过 wonda audio enhance 使用 replicate-resemble-enhance——降噪并去除混响。适用于声音录制听起来沉闷、有回声或带有背景噪声的情况。它不是通用的“让声音更好听”按钮;如果源音频已经很干净,处理后可能会变得更柔和。
  • 提取人声(分离人声/拆分音轨):通过 wonda audio extract-voice 使用 replicate-demucs——将音轨拆分为人声和伴奏。可用于从音轨中提取说话者或歌手,或分离人声背后的音乐。

原生同步语音(优先于 TTS + 对口型): Sora、Sora 2 Pro、Veo 3.1、Kling 3 和 Seedance 2 都能直接在视频中以任何语言生成对话,并内置嘴部动作。将台词(和语言)写入视频模型的 --prompt。不要将 elevenlabs-tts → sync-lipsync-v2-pro 串联起来,为静音生成结果伪造语音。

角色

角色是可重复使用的已保存组合(图像 + 可选语音音频),可在提示词中通过 @name 引用。服务会自动将图像、可选人脸视频和音频注入所选模型的相应输入槽位。适用于 Kling 3 Pro(start_image + element_1 + voice_audio)和 Seedance 2 Omni(ref_image_1 + ref_video_1 + ref_audio_1)。名称规则:必须以字母开头,长度为 1–31 个字符,且只能包含字母数字字符和 _/-。

提供商注意事项(Seedance 2 Omni): 提及角色时,API 会自动将 Seedance 路由到 MuAPI。Replicate 对 ref_audio_1 实施 15 秒时长限制,并会以 E005 — input flagged as sensitive 拒绝知名名人参考素材。对于以角色为核心的任务,MuAPI 是可靠的选择。即使使用 MuAPI,顶级名人参考素材(例如 Sydney Sweeney、Leonardo DiCaprio)仍会被拦截,并显示 "Face detected in uploaded image. Please use an image without real people."。非名人面孔和知名度较低的公众人物可以顺利通过。如果在真实人物参考素材上遇到此错误,请改用 Kling 3 Pro(其角色流程在服务端运行声音克隆,因此原始人脸音频不会经过内容审核分类器)。

从 Kling 片段中提取——从你喜欢的生成结果中提取一帧和语音:

VID=$(wonda generate video --model kling_3_pro --prompt "young man, grey tshirt, talking to camera" --wait --quiet)
VID_MEDIA=$(wonda jobs get inference $VID --jq '.outputs[0].media.mediaId')
wonda character from-media alex --source $VID_MEDIA --frame-ms 2500
wonda generate video --model kling_3_pro --prompt "@alex welcomes viewers to the channel" --wait -o alex-welcome.mp4

从头开始——生成一张肖像和一段 TTS 采样,然后将它们绑定:

IMG=$(wonda generate image --model nano-banana-2 --prompt "young woman, studio portrait" --wait --quiet)
IMG_MEDIA=$(wonda jobs get inference $IMG --jq '.outputs[0].media.mediaId')
AUD=$(wonda audio speech --model elevenlabs-tts --prompt "Hi, this is me" --params '{"voiceId":"21m00Tcm4TlvDq8ikWAM"}' --wait --quiet)
AUD_MEDIA=$(wonda jobs get inference $AUD --jq '.outputs[0].media.mediaId')
wonda character create maya --image $IMG_MEDIA --audio $AUD_MEDIA

列出 / 检查 / 更新 / 删除:wonda character list、wonda character get <name>、wonda character update <name> --audio $NEW、wonda character delete <name>。每次生成只能引用一个带有音频的角色。

提示词编写规则

从上到下遵循此瀑布式规则。使用第一个匹配的规则,然后停止。

  1. PASSTHROUGH — 如果用户说“使用我的原始提示词”/“逐字照用”/“不要增强” → 完全照抄用户的内容。零修改。

  2. IMAGE-TO-VIDEO — 当源图像输入视频模型时,只描述动作。模型可以看到图像。不要描述图像内容。

    • 正确示例:"gentle breathing motion, camera slowly pushes in, atmospheric lighting shifts"
    • 错误示例:"Two cats on a lavender background breathing softly"(描述了图像)
  3. EMPTY PROMPT(从头开始) — 将用户的原始请求作为提示词。不要添加风格描述、光线、构图或氛围。

    • 用户说“创建一张戴着太阳镜的猫的图片” → 提示词:"create an image of a cat with sunglasses"
    • 不要增强为 "A playful orange tabby wearing oversized reflective sunglasses, studio lighting, shallow depth of field"
  4. NON-EMPTY PROMPT(改编模板) — 保留结构和风格,仅替换内容以匹配用户的请求。提示词应保持直白且包含严格约束。

纵横比规则

分为三种情况,没有例外:

  1. 用户指定比例 → 使用该比例:--aspect-ratio 16:9
  2. 用户未提及比例 → 对社交内容(UGC、TikTok、Reels、Stories)明确设置 --aspect-ratio 9:16。竖屏是所有社交/营销视频的默认设置。
  3. 编辑现有媒体 → 使用 --aspect-ratio auto 以保留源尺寸

UGC 和社交内容始终采用竖屏(9:16)。 如果有人要求制作 TikTok、Reel、Story 或 UGC 视频,始终使用 --aspect-ratio 9:16。横屏仅用于 YouTube、演示文稿或用户明确要求的情况。

**方形(1:1)**受所有 Kling 模型和部分图像模型支持——用户要求制作 Instagram 信息流帖子时使用。

常见链式调用模式

这些模式展示了如何通过串联 CLI 命令来组合多步流水线。每一步的输出都会传递给下一步。

无需在步骤之间下载并重新上传。 每次生成和编辑都会在输出中产生媒体 ID。通过 --media 或 --audio-media 将该 ID 直接传递给下一条命令。 推理任务使用 --jq '.outputs[0].media.mediaId',编辑器任务使用 --jq '.outputs[0].mediaId'。 仅在最后一步使用 -o <file> 下载最终输出。

将图像制作成动画视频
MEDIA=$(wonda media upload ./product.jpg --quiet)
# No person in image → Seedance 2
wonda generate video --model seedance-2 --prompt "camera slowly pushes in, product rotates" \
  --attach $MEDIA --duration 5 --params '{"quality":"high"}' --wait -o animated.mp4
# Person in image → Kling (ONLY when attaching a reference image with a person)
wonda generate video --model kling_3_pro --prompt "the person turns and smiles" \
  --attach $MEDIA --duration 5 --wait -o person.mp4
替换视频中的音频(TTS 配音或音乐)
# Generate TTS
TTS_JOB=$(wonda audio speech --model elevenlabs-tts --prompt "The script" \
  --params '{"voiceId":"21m00Tcm4TlvDq8ikWAM"}' --wait --quiet)
TTS_MEDIA=$(wonda jobs get inference $TTS_JOB --jq '.outputs[0].media.mediaId')
# Mix onto video (mute original, full voiceover)
wonda edit video --operation editAudio --media $VID_MEDIA --audio-media $TTS_MEDIA \
  --params '{"videoVolume":0,"audioVolume":100}' --wait -o with-voice.mp4

仅在需要替换视频音频时使用此操作。Sora、Sora 2 Pro、Veo 3.1、Kling 3 和 Seedance 2 都能生成任何语言的原生同步语音——除非用户明确要求使用不同的配音,否则不要用 TTS 替换。切勿在 UGC/对镜讲话片段中为了“添加语音”而使用此步骤;应将对话写入视频模型的提示词中。

添加静态文本叠加

静态叠加(表情包文字、“chat did i cook”等)使用的字号比字幕小。它们用于营造氛围,不应成为画面的焦点。

wonda edit video --operation textOverlay --media $VID_MEDIA \
  --prompt-text "chat, did i cook" \
  --params '{"fontFamily":"TikTok Sans SemiCondensed","position":"top-center","sizePercent":66,"fontSizeScale":0.5,"strokeWidth":4.5,"paddingTop":10}' \
  --wait -o with-text.mp4

精选的 textOverlay + animatedCaptions 预设。 wonda edit {video,image,audio} 支持 --preset <name>(作用范围由 --operation 指定)。如果字段冲突,--params 中的值会覆盖预设值。

textOverlay(静态,顶部居中):

  • TikTok White Highlight — 白色圆角矩形框,黑色文字。
  • TikTok Black Highlight — 黑色圆角矩形框,白色文字。
  • TikTok Red Highlight — 红色(#E14135)圆角矩形框,白色文字。

animatedCaptions(由 STT 驱动,底部居中):

  • TikTok White Captions — 黑色文字,当前词以白色突出显示。
  • TikTok Black Captions — 白色文字,当前词以黑色突出显示。
  • TikTok Red Captions — 白色文字,当前词以红色(#E14135)突出显示。
wonda edit video --operation textOverlay \
  --preset "TikTok Red Highlight" --media <id> \
  --params '{"text":"YOUR HEADLINE"}' --wait -o ./out.mp4

textOverlay 通过捆绑的 hyperframes(Chromium)渲染器在本地渲染。现在已不再支持服务端图像 textOverlay。

字号指南:

  • 静态叠加:sizePercent: 66、fontSizeScale: 0.5、strokeWidth: 4.5
  • 动态字幕:sizePercent: 80、fontSizeScale: 0.8、strokeWidth: 2.5、highlightColor: rgb(252, 61, 61)
  • 两者的字体均为:TikTok Sans SemiCondensed
添加动态字幕(逐词显示并带时间轴)

animatedCaptions 操作会提取音频、转录内容,并逐词渲染动态字幕,一步完成。

wonda edit video --operation animatedCaptions --media $VIDEO_MEDIA \
  --params '{"fontFamily":"TikTok Sans SemiCondensed","position":"bottom-center","sizePercent":80,"strokeWidth":2.5,"fontSizeScale":0.8,"highlightColor":"rgb(252, 61, 61)"}' \
  --wait -o with-captions.mp4

要快速添加静态字幕(无时间轴,只在屏幕上显示文字),请将 textOverlay 与 --prompt-text 搭配使用:

wonda edit video --operation textOverlay --media $VIDEO_MEDIA \
  --prompt-text "Summer Sale - 50% Off" \
  --params '{"fontFamily":"TikTok Sans SemiCondensed","position":"bottom-center","sizePercent":80}' \
  --wait -o captioned.mp4
添加背景音乐
MUSIC_JOB=$(wonda generate music --model suno-music \
  --prompt "upbeat lo-fi hip hop, warm vinyl crackle" --wait --quiet)
MUSIC_MEDIA=$(wonda jobs get inference $MUSIC_JOB --jq '.outputs[0].media.mediaId')
wonda edit video --operation editAudio --media $VID_MEDIA --audio-media $MUSIC_MEDIA \
  --params '{"videoVolume":100,"audioVolume":30}' --wait -o with-music.mp4
串接编辑器输出

串接多个编辑器操作(例如 editAudio → animatedCaptions → textOverlay)时,从每个编辑器任务的输出中提取媒体 ID,并将其传递给下一步。注意,jq 路径与推理任务不同:

# Inference jobs: .outputs[0].media.mediaId
# Editor jobs:    .outputs[0].mediaId

EDIT_JOB=$(wonda edit video --operation editAudio --media $VID --audio-media $AUDIO \
  --params '{"videoVolume":0,"audioVolume":100}' --wait --quiet)
STEP1_MEDIA=$(wonda jobs get editor $EDIT_JOB --jq '.outputs[0].mediaId')

CAP_JOB=$(wonda edit video --operation animatedCaptions --media $STEP1_MEDIA \
  --params '{"fontFamily":"TikTok Sans SemiCondensed","position":"bottom-center","sizePercent":80,"strokeWidth":2.5,"fontSizeScale":0.8,"highlightColor":"rgb(252, 61, 61)"}' --wait --quiet)
STEP2_MEDIA=$(wonda jobs get editor $CAP_JOB --jq '.outputs[0].mediaId')

wonda edit video --operation textOverlay --media $STEP2_MEDIA \
  --prompt-text "Hook text" --params '{"position":"top-center","fontFamily":"TikTok Sans SemiCondensed","sizePercent":66,"fontSizeScale":0.5,"strokeWidth":4.5}' --wait -o final.mp4
合并多个片段

务必使用 ffmpeg 在本地合并。 服务端合并(wonda edit video --operation merge)在任何输入超过约 7MB 后都可能卡住 30 分钟以上。

下载每个 Wonda 媒体 ID,然后进行拼接。流复制速度快,但要求编解码器、配置和分辨率一致;如果报错,则改用重新编码:

wonda media download $CLIP1 -o /tmp/clip-1.mp4
wonda media download $CLIP2 -o /tmp/clip-2.mp4
wonda media download $CLIP3 -o /tmp/clip-3.mp4
cat > /tmp/concat.txt <<EOF
file '/tmp/clip-1.mp4'
file '/tmp/clip-2.mp4'
file '/tmp/clip-3.mp4'
EOF
ffmpeg -y -f concat -safe 0 -i /tmp/concat.txt -c copy /tmp/merged.mp4
# If stream-copy fails, re-encode:
# ffmpeg -y -f concat -safe 0 -i /tmp/concat.txt \
#   -c:v libx264 -preset medium -crf 18 -pix_fmt yuv420p -movflags +faststart \
#   -c:a aac -b:a 192k /tmp/merged.mp4

# Re-upload only if a downstream wonda step needs the mediaId.
MERGED_MEDIA=$(wonda media upload /tmp/merged.mp4 --quiet)

concat.txt 中的文件顺序就是播放顺序。完整的拼接参考请参阅 ffmpeg 技能。

分割场景 / 保留特定场景

有两种模式,请根据意图选择:

# Split mode (default) — returns EVERY detected scene as its own media.
# JSON output lists each scene under scenes[] ({mediaId,index,startS,endS}).
wonda edit video --operation splitScenes --media $VID_MEDIA \
  --params '{"mode":"split","threshold":0.5,"minClipDuration":2}' --json
# With -o, each scene downloads to a numbered file (out-1.mp4, out-2.mp4, ...);
# a single detected scene writes the path verbatim.
wonda edit video --operation splitScenes --media $VID_MEDIA \
  --params '{"mode":"split","threshold":0.5,"minClipDuration":2}' -o scenes.mp4

# Remove a scene (omit mode) — removes one scene, merges the rest into one file.
wonda edit video --operation splitScenes --media $VID_MEDIA \
  --params '{"mode":"omit","threshold":0.5,"minClipDuration":2,"outputSelection":"first"}' \
  --wait -o without-first.mp4
# outputSelection (omit mode only): "first", "last", or a 1-indexed number = which scene to REMOVE

“移除冻结的首帧”(Sora 视频中常见)时使用 omit 模式。要将所有场景分别导出为片段时,使用 split 模式。

图像编辑

任何图像编辑操作(img2img、移除背景、裁剪、文本叠加、矢量化)都有专属技能,其中包含完整的决策树、宽高比规则以及编辑时的模型选择流程:

wonda skill get image-edit

这里值得特别提醒一点:图像和视频的背景移除使用不同的模型(birefnet-bg-removal 和 bria-video-background-removal)。切勿混用。

唇形同步(最后手段——优先使用原生音频视频模型)

Sora、Sora 2 Pro、Veo 3.1、Kling 3 和 Seedance 2 都能生成任意语言的语音,并在视频中同步嘴部动作。这种方式的效果远胜于 sync-lipsync-v2-pro:唇部物理效果和光线更好、成本更低,也无需进行第二轮推理。对于任何对话类 UGC、广告或发言人视频,都应将对白直接写入视频模型的提示词——不要串接 TTS + lipsync。

只有当用户明确提供现成的视频和音频片段,并要求将口型与该音频对齐时,才使用 sync-lipsync-v2-pro。如果用户要求默认通过 lipsync 让角色说话,应予以说明并建议改用原生音频视频模型:它们是更好的工具,且支持任意语言。

wonda generate video --model sync-lipsync-v2-pro --attach $VIDEO_MEDIA,$AUDIO_MEDIA --wait -o synced.mp4
视频超分辨率
wonda generate video --model topaz-video-upscale --attach $VIDEO_MEDIA \
  --params '{"upscaleFactor":2}' --wait -o upscaled.mp4
剪辑(长视频 → 竖屏短视频)

wonda clipping 接收一段长视频(播客、访谈、出镜讲话),并生成竖屏短视频。片段选择由大模型驱动,并支持自然语言 --brief,因此你可以指定想要的片段,而不是只追求泛泛的爆红效果。

V1 默认以 9:16 渲染,采用人脸跟踪重构画面(LR-ASD 活跃说话人检测 + One-Euro 稳定器),并为每个片段使用现有的 animatedCaptions op 和顶部三分之一区域的钩子叠加层。传入 --reframe blur-fill,可将完整的横屏源视频保留在竖屏画布中,并使用模糊背景。

**翻译字幕:**传入 --caption-language <code>(ISO-639-1,例如 en),即可在保留原始音频的同时,以其他语言渲染字幕。每个片段的转录文本会逐句翻译,并保留说话时间,因此字幕能与音频保持同步。不传入此标志,则字幕使用口述语言。使用 --restyle 时,除非另行指定语言,否则会继承父任务的语言,因此你可以轻松为已剪辑的任务生成英文字幕版本(复用转录文本,无需重新转录)。

异步处理:POST /api/v1/clipping 会返回一个 clippingJobId;CLI 在使用 --wait 时会轮询 GET /api/v1/clipping/jobs/{id}。传入 --output <dir>,CLI 会下载每个渲染后的片段及一个 plan.json。

身份验证:已包含在付费方案中。

来源:--url 接受 YouTube 链接和直接的 mp4 URL。

wonda clipping --url "<youtube-url>" --brief "the most controversial moments" --wait

YouTube 链接可用;长视频在开始转录前可能需要几分钟导入。如果 YouTube 导入失败,请先在本地下载文件并上传,然后使用 --media 进行剪辑:

yt-dlp -o /tmp/source.mp4 \
  -f "bv*[ext=mp4][height<=720]+ba[ext=m4a]/b[ext=mp4][height<=720]" \
  --merge-output-format mp4 "<youtube-url>"
MEDIA=$(wonda media upload /tmp/source.mp4 --no-transcode --quiet)

--no-transcode 会跳过服务端标准化处理,让长视频源在几秒内即可使用,而非等待几分钟(否则,1 h 的上传会先转码约 19 min,之后才能开始剪辑)。剪辑会自动处理所选片段中的不兼容格式(AV1、旋转的手机视频)。如果上传的内容计划直接发布或编辑,而不进行剪辑,请勿使用此标志。

# Plan only — fast, no render
wonda clipping --media $MEDIA --brief "the most controversial moments" --dry-run --wait

# Full pipeline: select + render + download
wonda clipping --media $MEDIA \
  --brief "the most controversial moments" \
  --caption-preset "TikTok Red Captions" \
  --hook auto \
  --wait --output ./clips/

# Translate captions to English (original audio kept)
wonda clipping --media $MEDIA --caption-language en --wait --output ./clips/

# Re-caption an existing job into English (reuses STT + clip picks, ~$0)
wonda clipping --restyle <jobId> --caption-language en --wait --output ./clips/

# Filter by speaker (uses ElevenLabs diarization labels)
wonda clipping --media $MEDIA --speaker SPEAKER_00 --wait --output ./clips/

# Speaker rename for readable rationales
wonda clipping --media $MEDIA --speaker Joe \
  --speaker-map '{"SPEAKER_00":"Joe","SPEAKER_01":"Guest"}' --wait --output ./clips/

# Tune count and durations — pick a target length with a tolerance
wonda clipping --media $MEDIA --brief "punchy one-liners" \
  --count 5 --duration 20 --tolerance 5 --wait --output ./clips/

# Or specify an explicit min/max range instead (mutually exclusive
# with --duration/--tolerance)
wonda clipping --media $MEDIA --brief "punchy one-liners" \
  --count 5 --min-duration 8 --max-duration 30 --wait --output ./clips/

# Auto-pick FX preset per clip from a catalog
wonda clipping --media $MEDIA --auto-preset \
  --preset-catalog '[{"slug":"flash_glow","description":"glow + scene flash"},{"slug":"text_glow","description":"per-word text glow"}]' \
  --wait --output ./clips/

任务状态结构(由 GET /api/v1/clipping/jobs/{id} 返回):

{
  "clippingJobId": "...",
  "status": "succeeded",
  "stage": "succeeded",
  "progress": 1,
  "plan": {
    "sourceDurationSec": 1800.5,
    "speakers": ["SPEAKER_00", "SPEAKER_01"],
    "clips": [
      {
        "start": 12.4,
        "end": 38.7,
        "title": "Why he quit the agency",
        "hookText": "He admits…",
        "rationale": "Concedes \"the agency model is dead\" then explains why...",
        "score": 87,
        "dominantSpeaker": "SPEAKER_00",
        "reframeMode": "blur-fill",
        "preset": null,
        "mediaId": "uuid-of-rendered-clip",
        "url": "https://storage.googleapis.com/.../clip.mp4"
      }
    ]
  },
  "error": null
}

编辑器操作参考

操作输入关键参数
animatedCaptionsvideo_0字体系列、位置、sizePercent、fontSizeScale、strokeWidth、highlightColor
textOverlayvideo_0 + prompt字体系列、位置、sizePercent、fontSizeScale、strokeWidth
editAudiovideo_0 + audio_0videoVolume(0-100)、audioVolume(0-100)
mergevideo_0..video_4按播放顺序处理
overlayvideo_0(背景)+ video_1(前景)位置、resizePercent
splitScreenvideo_0 + video_1targetAspectRatio(16:9 或 9:16)
trimvideo_0trimStartMs、trimEndMs(毫秒)
cropvideo_0aspectRatio(16:9/9:16/1:1/4:5/21:9/custom)或 cropPercent+cropAxis。基于比例/百分比,而非像素坐标
volumevideo_0volume(0-100)或 muted
speedvideo_0speed(倍数:2 = 快 2 倍)
extractFramevideo_0timestampMs 或 timestampPercent(输出图像)
extractAudiovideo_0提取音轨(输出 mp3)
reverseVideovideo_0倒放
splitScenesvideo_0mode(split 返回所有场景 / omit 返回一个合并文件)、threshold、outputSelection(仅 omit 时使用)
skipSilencevideo_0maxSilenceDuration(默认值为 0.03)
audioTrimaudio_0trimStartMs、trimEndMs(毫秒)
imageCropimage_0cropPixelX、cropPixelY、cropPixelWidth、cropPixelHeight(精确像素矩形)
textOverlayvideo_0(图像)与视频 textOverlay 相同 — 可用于图像,输出图像(png/jpg)

crop 与 imageCrop: 视频 crop 基于比例/百分比(aspectRatio 或 cropPercent+cropAxis);它不接受像素坐标,使用 cropPixelX/Y/Width/Height 会报错。若要指定精确像素矩形,请使用 imageCrop。运行 wonda operations info <operation>,查看任意操作的完整参数列表、默认值和取值范围。

有效的 textOverlay 字体:Inter、Montserrat、Bebas Neue、Oswald、TikTok Sans、TikTok Sans Condensed、TikTok Sans SemiCondensed、TikTok Sans SemiExpanded、TikTok Sans Expanded、TikTok Sans ExtraExpanded、Nohemi、Poppins、Raleway、Anton、Comic Cat、Gavency 有效的位置:top-left、top-center、top-right、center-left、center、center-right、bottom-left、bottom-center、bottom-right

营销与分发

# Connected social accounts
wonda accounts instagram
wonda accounts tiktok

# Analytics
wonda analytics instagram
wonda analytics tiktok
wonda analytics meta-ads

# Organic owned-post analytics use platform-specific read commands:
# wonda x analytics, wonda linkedin analytics, wonda reddit analytics.
# The global analytics group above is for connected marketing APIs.

# Scrape competitors
wonda scrape social --handle @nike --platform instagram --wait
wonda scrape social-status <taskId>                   # Get results of a social scrape
wonda scrape cancel <taskId>                          # Cancel any public scrape task
wonda scrape ads --query "sneakers" --country US --wait
wonda scrape ads --query "sneakers" --country US --search-type keyword \
  --active-status active --sort-by impressions_desc --period last30d \
  --media-type video --max-results 50 --wait
wonda scrape ads-status <taskId>                      # Get results of an ads search

# Download a single reel or TikTok video
SCRAPE=$(wonda scrape video --url "https://www.instagram.com/reel/ABC123/" --wait --quiet)
# → returns scrape result with mediaId in the media array

# Publish
wonda publish instagram --media <id> --account <accountId> --caption "New drop"
wonda publish instagram --media <id> --account <accountId> --caption "..." --alt-text "..." --product IMAGE --share-to-feed
wonda publish instagram-carousel --media <id1>,<id2>,<id3> --account <accountId> --caption "..."
wonda tiktok creator-info --account <accountId>      # Live privacy options + comment/duet/stitch defaults
wonda publish tiktok --media <id> --account <accountId> --caption "New drop" --privacy PUBLIC_TO_EVERYONE
wonda publish tiktok --media <id> --account <accountId> --caption "..." --privacy PUBLIC_TO_EVERYONE \
  --disable-comment --commercial-disclose --brand-organic
wonda publish tiktok-carousel --media <id1>,<id2> --account <accountId> --caption "..." \
  --privacy PUBLIC_TO_EVERYONE --cover-index 0

# History
wonda publish history instagram --limit 10
wonda publish history tiktok --limit 10

# Browse media library
wonda media list --kind image --limit 20
wonda media info <mediaId>
X/Twitter

支持读取、写入和社交关系图谱。

⚠️ 反欺诈警告:不要探测刚粘贴的 Cookie。 刚收到 Cookie(你自己的或用户的)时,首次请求必须执行用户实际想要的操作,而不是 wonda x auth check、wonda x home 或任何会触发探测的操作。在新 IP、设备或进程上突然发起大量活动,是 X(以及 Reddit / LinkedIn / IG)识别凭证盗窃的典型信号,Cookie 会被影子封禁或彻底失效。如果必须验证,请使用 wonda x auth check --account <name> --via wab(该命令会通过账号现有的已登录浏览器会话执行:使用相同的 IP、指纹和浏览历史),不要从全新进程发起原始 API 请求。

# Auth setup (run `wonda x auth --help` for details)
wonda x auth set --auth-token <token> --ct0 <ct0>
wonda x auth set --account <name> --auth-token <...> --ct0 <...>  # multi-account
wonda x auth check                                              # raw probe, see warning above
wonda x auth check --account <name> --via wab                   # safe: routes via account's WAB session
wonda x auth status --account <name>                             # local provenance, generation, ownership, cookie names, and risk; never probes
wonda x auth refresh --account <name> --persona <persona>       # stale WAB to disk sync, then WAB-side session check; never raw-probes
wonda x browser-bootstrap --account <name>                       # inject stored cookies into running bound WAB personas

# Read
wonda x search "sneakers" -n 20                     # Search tweets (sort: latest, current, top; time: day, week, month, year, all)
wonda x --freshen search "sneakers" --via cookies   # refresh the selected stale cookie store before one cookies-only read
wonda x search "sneakers" --sort top --time week -n 20  # Top tweets from the last week
wonda x user @nike                                   # User profile
wonda x user-tweets @nike -n 20                      # User's recent tweets
wonda x read <tweet-id-or-url>                       # Single tweet
wonda x analytics <tweet-id-or-url>                  # Tweet metrics: viewCount, likeCount, retweetCount, replyCount
wonda x insights <tweet-id-or-url>                   # Alias for x analytics
wonda x replies <tweet-id-or-url>                    # Replies to a tweet
wonda x thread <tweet-id-or-url>                     # Full thread (author's self-replies)
wonda x home                                         # Home timeline (--following for Following tab)
wonda x bookmarks                                    # Your bookmarks
wonda x likes                                        # Your liked tweets
wonda x following @handle                            # Who a user follows
wonda x followers @handle                            # A user's followers
wonda x lists @handle                                # User's lists (--member-of for memberships)
wonda x list-timeline <list-id-or-url>               # Tweets from a list
wonda x news --tab trending                          # Trending topics (tabs: for_you, trending, news, sports, entertainment)
wonda x mentions -n 20                               # Recent replies and @mentions directed at your account
wonda x dm inbox -n 20                               # X DM conversations, default cookie path
wonda x dm requests -n 20                            # X DM message requests, default cookie path
wonda x dm read <conversation-id> -n 50              # Messages in one conversation
wonda x dm read <conversation-id> --via wab          # Same read routed through the WAB browser session

# Write (tweet/reply/engagement defaults to --via wab; X DM sends are wab-only)
wonda x tweet "Hello world"                          # Post a tweet
wonda x tweet "Hello world" --account <name> --via wab  # Full stealth via real browser
wonda x tweet "Hello world" --attach ~/clip.mp4      # Attach image/gif/video (up to 4)
wonda x reply <tweet-id-or-url> "Great point"        # Reply
wonda x like <tweet-id-or-url>                       # Like
wonda x unlike <tweet-id-or-url>                     # Unlike
wonda x retweet <tweet-id-or-url>                    # Retweet
wonda x unretweet <tweet-id-or-url>                  # Unretweet
wonda x follow @handle                               # Follow
wonda x unfollow @handle                             # Unfollow
wonda x feed-engage --authors "a,b" --duration 5m    # Scroll the feed and like posts from these authors (wab-only)
wonda x feed-engage --keywords "wonda alternative" --reply --max-reply 3  # Monitor search results, gate relevance, reply via WAB
wonda x dm send <conversation-id> "Hey, quick note"  # Send in an existing DM thread, wab-only
wonda x dm send <conversation-id> "Hey" --dry-run    # Type only, do not click Send
wonda x dm accept <conversation-id> --dry-run        # Open a message request without accepting it
wonda x dm accept <conversation-id>                  # Accept an incoming DM request, wab-only
wonda x dm start @handle --text "Hey, quick note"    # Start or reuse a DM by handle, wab-only
wonda x dm passcode set --account <name>             # Save encrypted XChat passcode for that account
wonda x dm passcode status --account <name>          # Show whether a passcode is configured

# Maintenance
wonda x refresh-ids                                  # Refresh cached GraphQL query IDs from X's JS bundles

所有分页命令均支持:-n <count>、--cursor、--all、--max-pages、--delay <ms>。X 提供新游标时,即使页面为空或仅包含重复内容,推文读取也会继续,直至达到页面数上限。

x follow 和 x unfollow 会根据可访问标签匹配目标账号的个人资料控制项。创作者个人资料使用其“取消关注”菜单;普通个人资料使用确认面板。两种操作以及恢复点击均不会点击订阅控件,只有目标个人资料上的关注标签发生变化才算成功。

如果成员在公开简介中明确填写了联系方式,或 X 为该个人资料提供了展开后的 URL 实体,wonda x user 会附加 emails 和 links 字段。这些字段为只读,效果等同于手动查看个人资料。不会推断电子邮件、补充数据、存储信息或抓取 DOM。

推文模式: tweet 命令有两种传输方式:

  • --via cookies(内部 API): 使用 X 的内部 GraphQL(≤280 个字符时使用 CreateTweet,长篇 Premium 推文使用 CreateNoteTweet)。速度快(<1s),支持使用 --attach 附加媒体。X 轮换查询 ID 或功能标记时,偶尔会因错误 226 失败。遇到这种情况时,请通过 twitter-tone-research/_artifacts/scripts/capture-ct-bw.mjs 重新捕获,并更新 xclient/ 中的三个参数。
  • --via wab(写入操作的默认方式): 通过账号的 WAB Chromium 执行(首次使用 --via wab 时会自动启动),打开 x.com 发帖界面,以模拟真人的随机延迟输入内容,然后点击“发布”。支持使用 --attach 附加图片/GIF/视频(最多 4 个);文件通过 Playwright 的 setInputFiles 写入隐藏的发帖输入框,不会打开系统文件选择器;脚本会等待 X 完成上传流程后再提交(视频最长等待 5 分钟)。指纹识别风险为零。速度较慢(纯文本约 10s,附带视频约 30-90s),但完全不受上游变化影响:无需维护 queryIds、功能标记或请求结构。隐身浏览器和 Chromium 只需通过 wonda wab install 安装一次(约 315 MB,幂等)。Cookie 存储在 ~/.wonda/x-cookies/<account>.json 中,并通过 account-bindings.json 绑定到账号的角色身份。wonda x reply --attach 仅支持 wab(不支持 Cookie 路径)。
入站互动

收到的互动是指他人对分身自身内容的入站活动:回复、提及、评论和私信。这与对外发布、点赞和关注的方向相反。

它不是关键词监控,不是已发送邀请或外联的接受情况追踪,也不是对外操作台账。关键词监控请使用平台搜索命令。对外操作统计请使用 wonda actions。

wonda inbound                                      # New inbound items for every local persona
wonda inbound --persona brubakerwise              # One persona
wonda inbound --platform x -n 20                  # Only X mentions/replies
wonda inbound --platform linkedin                 # LinkedIn notifications
wonda inbound --platform reddit                   # Reddit classic inbox
wonda inbound --all                               # Dump fetched items without high-water diff or state write

wonda inbound 仅调用直接读取客户端:X 提及/回复、LinkedIn 通知和 Reddit 经典收件箱。输出始终为规范化 JSON:

{
  "new_count": 1,
  "items": [
    {
      "persona": "brubakerwise",
      "platform": "x",
      "account": "brubakerwise",
      "kind": "reply",
      "author": "someone",
      "text": "Useful point",
      "target_id": "2069000000000000000",
      "item_id": "2069000000000000001",
      "timestamp": "2026-06-22T12:00:00Z",
      "url": "https://x.com/someone/status/2069000000000000001"
    }
  ]
}

默认情况下,它会将每个人设/平台/账号的高水位标记保存在 ~/.wonda/wab/personas/<persona>/inbound-state.json,并且仅输出比上次运行更新的条目。状态损坏或缺失时,会按首次运行处理。--all 会跳过状态的读取和写入,并返回完整的已获取条目集。

X 私信: 默认情况下,wonda x dm inbox、wonda x dm requests 和 wonda x dm read 通过基于 Cookie 的 xclient 路径读取,也可使用 --via wab,通过浏览器会话传输以保持一致。requests 会返回不受信任/消息请求收件箱,以便明确处理接收方的接受操作。wonda x dm send、wonda x dm start 和 wonda x dm accept 是仅限 WAB 的 DOM 写入操作:发送时会打开真实的 X 消息界面,在 [data-testid="dmComposerTextInput"] 中输入内容,并点击编辑框的发送按钮;接受时会通过 Chat 打开请求对话,并点击可见的 Accept/Allow 控件。start 会在发送前确认所选建议的屏幕名称与请求的账号名一致;如果 --account 或人设绑定提供了账号信息,WAB 私信写入操作会验证当前激活的 X 浏览器账号。如果 x dm send 或 x dm start 失败并返回 recipient_cannot_receive_dm,则表示 X 在发送前拒绝了这条私信。请确认接收方可以接收发送方的私信:可能需要互相关注/建立联系,且接收方可能需要先接受任何待处理的消息请求,然后才能重试。如果 X 显示加密的 XChat 密码门控,请使用 wonda x dm passcode set --account <name> 保存密码;密码会采用与 Cookie 邻近存储相同的本地密钥模式在本地加密,绝不会被打印或包含在故障包中。在 X 提供需要进一步处理的对话前,尚不支持更深入的 XChat/Juicebox 消息解密/加密功能。

LinkedIn

支持搜索、个人资料、公司、消息和互动。

⚠️ 与 X 相同的反欺诈注意事项:不要探测刚粘贴的 Cookie。 新 Cookie 的首次请求就是实际操作,绝不是检查。LinkedIn 的反欺诈措施在所有平台中最为激进(强制注销、密码重置、账号标记)。如果必须验证,请使用 wonda linkedin auth check --account <name> --via wab,通过该账号现有的 WAB 会话进行操作。

# Auth setup (run `wonda linkedin auth --help` for details)
wonda linkedin auth set --li-at-value <v> --jsessionid-value <v>
wonda linkedin auth set --account brand-A --li-at-value <...> --jsessionid-value <...>  # multi-account
wonda linkedin auth check                                              # raw probe, see warning above
wonda linkedin auth check --account <name> --via wab               # safe: routes via account's WAB session
wonda linkedin auth status --account <name>                        # local-only: cookie provenance (login vs paste) + 429-risk, never probes
wonda linkedin auth refresh --account <name> --persona <persona>   # local freshness preflight; stale WAB → disk sync, never raw-probes

# Read
wonda linkedin me                                    # Your identity
wonda linkedin search "data engineer" --type PEOPLE  # Search (types: PEOPLE, COMPANIES, ALL)
wonda linkedin profile johndoe                       # View profile (vanity name or URL)
wonda linkedin profile johndoe --via public          # View public profile data through the paid scrape API
wonda linkedin profile johndoe --via public --force-refresh --idempotency-key run-123
wonda linkedin enrich johndoe janedoe                # Batch profile enrichment through cookies, max 25 inputs
wonda linkedin enrich johndoe janedoe --via public   # Paid public enrichment task, default waits for completion
wonda linkedin enrich johndoe --via public --no-wait # Create task only, then poll GET /scrape/linkedin-profiles/{taskId}
wonda linkedin company google                        # View company page
wonda linkedin resolve <fsd-profile-id>...            # Resolve ACoAA member ids to public vanities (cookie-only, cached per account)
wonda linkedin conversations                         # List message threads
wonda linkedin conversations --resolve               # Fill missing participant/sender vanityName fields
wonda linkedin messages <conversation-urn>           # Read messages in a thread
wonda linkedin messages <conversation-urn> --resolve # Fill missing sender vanityName fields
wonda linkedin conversation-state <vanity-or-url> --via wab # Read only that member's 1:1 thread summary; never lists the inbox or prints bodies
wonda linkedin notifications -n 20                   # Recent notifications
wonda linkedin connections                           # Your own connections (recently-added order, each with connectedAt)
wonda linkedin connections johndoe                   # A member's connections visible to you (connectionOf search; relevance order, no dates; --degree 1|2|3 filters by your distance; --all enumerates)
wonda linkedin sent-invitations                      # Pending sent invites + audit reconciliation; cookies default, --via wab supported
wonda linkedin invitations                           # Incoming connection requests with notes and sharedSecret (cookie-only read)
wonda linkedin connection-status johndoe janedoe     # Per-member: connected / pending (in|out) / not_connected (cookie-only)
wonda linkedin saves                                 # Your saved posts (My Items → Saved posts; --all, --enrich for likes/comments)
wonda linkedin analytics <activity-id>               # Owned post analytics: impressions, uniqueViewers, engagements, profileViews when exposed
wonda linkedin analytics --profile                   # Profile-view analytics when LinkedIn exposes it for the account
wonda linkedin reactions <activity-id>               # Reactions with reactor profiles + type
wonda linkedin comment-reactors <comment-url-or-activityId:commentId> # Reactions on a specific comment with reactor profiles + type
wonda linkedin browser-bootstrap                     # Inject stored cookies into the WAB profile (one-time + on rotation)
wonda linkedin comments <activity-id> --account <name> --via wab  # Commenters with profile + vanity (auto-spawns WAB)
wonda linkedin activity johndoe                      # Structured recent activity for one member. --type all (their posts + reshares, default) | comments (posts they commented on, with their own comment text) | reactions (posts they reacted to, with reaction type). Each item carries the underlying post's published time, permalink, author (name + profile URL), and text; --count N (default 20)
wonda linkedin activity johndoe janedoe --engine cloud --via wab --json # Batches accept 2-10 profiles with --count up to 25 (250 items maximum) through the cloud twin's live WAB session; a single profile accepts --count up to 100. Never reads cookie files from this machine or falls back to local execution; batch output preserves per-profile errors, stops immediately on a global rate-limit signal, marks remaining profiles not_attempted, and reports visibility as visible when activity exists or the rendered activity surface shows an accessible empty state, not_visible only when LinkedIn explicitly says it is hidden, or unknown.
wonda linkedin search-posts "<keyword>" --date-range past-week --account <name>  # Keyword to recent posts + author profile (Voyager content API over cookies by default, returns the activity id + exact post time; --via wab for the DOM-scrape fallback; for social listening run `wonda skill get linkedin-social-listening`)

# Sales Navigator (seat-gated: the LinkedIn account needs an SN seat; cookie reads, each verb also runs as a cloud twin action)
wonda linkedin salesnav search "VP marketing" --seniority CXO --region "Berlin, Germany"  # Faceted lead search; also --industry/--company/--function/--connection-of; '~' prefix excludes a value; --csv exports. Facet flags take a plain name OR a facet id: names auto-resolve (companies + connection-of via the global typeahead; titles/regions/industries/functions/schools via the facet typeahead, where CURRENT_TITLE/PAST_TITLE are served under type TITLE and REGION under BING_GEO; SENIORITY_LEVEL and YEARS_OF_EXPERIENCE resolve offline against recorded tables first: seniority 100 In Training, 110 Entry Level, 120 Senior, 130 Strategic, 200 Entry Level Manager, 210 Experienced Manager, 220 Director, 300 Vice President, 310 CXO, 320 Owner / Partner; names the tables miss fall back to the typeahead under types SENIORITY_V2 / TENURE, so LinkedIn's own labels like "3 to 5 years" also work). An ambiguous name fails listing the candidate ids with their subtext (industry/location for companies, position/company for people) so you pick and re-run with the id. Each lead already carries the card decoration the search response inlines for free (no per-lead read): connection degree, current-role tenure + start month/year, and spotlight badges (Recently hired, N recent posts). Education/graduation year is NOT in search; add it with `salesnav profile <urn> --enrich`. Default transport is the sales-api JSON path over cookies; pass `--via wab` for the DOM-scrape fallback (drives the logged-in SN SPA and scrapes the rendered result cards) which survives LinkedIn rotating the search decoration id, at the cost of the inlined fields the rendered card does not show (member urn, exact position start dates, the saved/viewed/premium flags, and list-membership counts). Connection degree, current-role tenure, and spotlight badges are still scraped. Same `SalesLead` output and `--csv` columns either way (the CSV flattens the primary JSON lead fields: identity, current role + most recent past role, tenure, spotlight labels, saved/viewed/openLink flags, list count, both URNs; deep nests like the full position list and company URNs stay JSON-only). A sales-api 403 self-heals: the CLI drives the persona WAB to linkedin.com/sales once to mint the SN li_a cookie, syncs cookies, and retries; an error means either recovery cannot help (dead LinkedIn login, no SN seat) or the recovery step itself failed (e.g. the WAB could not start or sync), and the message says which. Recovery is deliberately disabled under explicit credential overrides (--li-at/--jsessionid or the LI_AT/LI_JSESSIONID env), since it reloads the on-disk account store and could switch identity: those invocations surface the manual runbook instead.
wonda linkedin salesnav search --school "HEC Paris" --past-company SpaceX --past-title 3 --years-of-experience 6-10  # Background facets: school/university, past employer, past job title, years-of-experience buckets (id or label, trailing 'y' optional: 1 <1y, 2 1-2y, 3 3-5y, 4 6-10y, 5 10+y); --title filters current job title
wonda linkedin salesnav facets SCHOOL "HEC Paris"    # Resolve a facet value name to the id the search flags take (no args lists the filter types). Companies do NOT resolve here (the facet typeahead returns [] for CURRENT_COMPANY/PAST_COMPANY): resolve company names via `salesnav typeahead`, or just pass the name to the search flag and let it auto-resolve. The command auto-aliases CURRENT_TITLE/PAST_TITLE to TITLE, REGION to BING_GEO, SENIORITY_LEVEL to SENIORITY_V2, and YEARS_OF_EXPERIENCE to TENURE (the types the typeahead actually serves), so `facets SENIORITY_LEVEL` lists the live seniority values
wonda linkedin salesnav --help                       # More seat-gated reads: saved-searches, lists, profile, typeahead, recommended leads|companies, alerts, recent, personas, notifications, warm-intro, insights
wonda linkedin salesnav profile "urn:li:fs_salesProfile:(ACwAA...,NAME_SEARCH,eQ3R)"  # Resolve one or more SN leads by fs_salesProfile urn (name + picture); add --enrich for each lead's education (school/degree/field/years), full experience history, and years-of-experience (opt-in; ~2 extra Voyager reads per lead, capped at 25)
wonda linkedin salesnav save-lead "urn:li:fs_salesProfile:(ACwAA...,NAME_SEARCH,eQ3R)"  # Save a lead (WAB WRITE: clicks Save on the /sales/lead/ page; no cookies path). Idempotent: an already-saved lead reports changed:false without clicking. --unsave selects the lead's checkbox on the saved-leads search and clicks the results toolbar's direct Unsave control (primary path, then VERIFIES the result); the old card-overflow menu flow is only a fallback — LinkedIn ignores that menu action (verified 2026-07-22), so a fallback run still ends in an honest sn_unsave_inert error. Also accepts the bare-token urn or a raw lead id, like `salesnav profile`
wonda linkedin salesnav create-list "Berlin CTOs" --description "Q3 outbound"  # Create a lead list (wab-only write: clicks through the SN lists UI in the persona browser) and print its numeric id; SN allows duplicate names, the result carries duplicateName:true when one already existed
wonda linkedin salesnav delete-list 7478163673497243649  # Delete a lead list by its numeric id (wab-only write). Idempotent: a missing id reports notFound and exits 0
wonda linkedin salesnav message "urn:li:fs_salesProfile:(ACwAA...,NAME_SEARCH,eQ3R)" --text "Hi Ada, ..." --expect-name "Ada Fixture"  # PREVIEW-FIRST (wab-only, no cookies path): composes a message/InMail on the lead's SN page and returns the EXACT composed text (previewed:true, sent:false) WITHOUT sending. A human must approve that text; add --send to actually send (a separate, explicit step). In --send mode the composed field is re-read right before Send and must equal --text (and --subject when present) or the send aborts (compose_text_mismatch) — a message can only be sent when the field verifiably holds the approved text. --expect-name is MANDATORY: the action verifies the rendered lead name before touching the compose and refuses on mismatch (recipient_mismatch). 1st-degree leads get a regular message; others get the InMail form, where --subject fills the subject (skipped when no subject field renders). SN blocks (no InMail credits, lead not messageable) fail with the dialog text and a structured reason.
wonda linkedin salesnav connect "urn:li:fs_salesProfile:(ACwAA...,NAME_SEARCH,eQ3R)" --expect-name "Ada Fixture" --note "Hi Ada, ..."  # PREVIEW-FIRST (wab-only, no cookies path): opens SN's Connect flow on the lead's page (top-card Connect or the overflow "..." menu item, clicked with a real OS mouse since SN hue-menu items can be inert), fills the optional --note, and returns it (previewed:true, sent:false) WITHOUT sending. A human must approve; add --send to actually send (a separate, explicit step). In --send mode the note field is re-read right before Send and must equal --note or the send aborts (connect_note_mismatch). --expect-name is MANDATORY: the action verifies the rendered lead name before touching the invite and refuses on mismatch (recipient_mismatch). A 1st-degree lead (or one with an outstanding invite) has no Connect affordance and reports alreadyConnected cleanly. SN blocks (weekly invitation limit, cannot connect) fail with the dialog text and a structured reason.
wonda linkedin salesnav list-add 7478163673497243649 "urn:li:fs_salesProfile:(ACwAA...,NAME_SEARCH,eQ3R)"  # Save a lead into a lead list (list id or exact name; urn from `salesnav search`). WAB-only write: toggles the list in the lead page's Save flyout. `list-remove` undoes it (falls back to the list page's row action). Both idempotent: already-member/non-member exits 0 with changed:false
wonda linkedin salesnav save-search "UK founders" --seniority 310 --region 101165590  # Save the search on the seat (wab-only WRITE: renders the search in the persona WAB and flips the filter panel's Save-search toggle; same keywords + facet flags as `salesnav search`; idempotent — already saved reports changed:false). The current SN UI auto-names saved searches: the <name> positional is advisory only and NOT applied (output carries named:false; rename in the SN UI, or delete-saved-search and re-create there). Read loop: `salesnav saved-searches` then shows each saved search's id and newHitsCount (new matching leads since lastViewedAt)
wonda linkedin salesnav delete-saved-search 50123456  # Delete a saved search by id (from `salesnav saved-searches`); wab-only WRITE, idempotent: a missing id reports notFound:true and exits 0

# WAB lifecycle (see `wonda wab --help` for the full surface: start/stop/status/install/bind/sync-cookies/logs)
wonda linkedin enrich-engagers --activity-id <id>    # Scrape engagers + enrich each with profile + current employer (joined JSON; --company-detail=false skips company page lookups)
wonda linkedin enrich-engagers --activity-id <id> --profile-source public  # Keep engager collection logged-in, use paid public profile detail

# Write
wonda linkedin visit <vanity-name> --account <name>  # Visit a real profile page in the WAB, dwell, and optionally notify the target
wonda linkedin connect <vanity-name> --message "Hey!" # Send connection request with note
wonda linkedin connect <vanity-name> -m "Hey!" --account <name> --via wab  # Full stealth via the account's persona
wonda linkedin follow <vanity-name-or-url> --account <name> # Follow a member or company (wab-only; primary button or under "More"; idempotent)
wonda linkedin comment <activity-id> --account <name> # Add a comment (wab-only: needs SDUI render state)
wonda linkedin reply-comment <activity-id> <comment-id> "Good point." --account <name> # Reply under a specific comment (wab-only)
wonda linkedin mute <vanity-name-or-url> --account <name> # Mute a member's posts in the actor's feed (wab-only; keeps the connection)
wonda linkedin edit-post <activity-id-or-url> "Updated body" # Edit your own post (wab-only: menu -> Edit post -> Save -> verify)
wonda linkedin edit-comment <activity-id-or-url> <comment-id> "Updated comment" # Edit your own comment (wab-only: comment menu -> Edit -> Save -> verify)
wonda linkedin like <activity-urn>                   # Like a post
wonda linkedin like <activity-urn> --comment <commentId>        # Like a specific comment (wab-only)
wonda linkedin like <activity-urn> --comment <commentId> --reaction love  # React to a specific comment
wonda linkedin unlike <activity-urn>                 # Remove a like
wonda linkedin unlike <activity-urn> --comment <commentId>      # Remove your reaction from a specific comment (wab-only)
wonda linkedin send-message <conversation-urn> "Hi!" # Send a message
wonda linkedin inmail <vanity-name> --message "Hi!" --subject "Quick question" # Native LinkedIn InMail (wab-only)
wonda linkedin post "Excited to announce..."         # Create a post
wonda linkedin post "A quick visual note" --media ./image.png --via wab # Create a post with media
wonda linkedin delete-post <activity-id>             # Delete a post
wonda linkedin delete-comment <comment-url-or-activityId:commentId> # Delete your own comment (WAB: comment menu -> Delete -> confirm -> verify)
wonda linkedin feed-engage --authors "a,b" --duration 5m  # Scroll the feed and like posts from these authors (wab-only)
wonda linkedin feed-engage --keywords "short form video" --reply --max-reply 3  # Monitor content search, gate relevance, comment via WAB
wonda linkedin feed-engage --authors "a,b" --engage-comments --max-comment-engage 2  # Also react to matching comments on engaged posts
wonda linkedin engage-commenters --post <activity-id-or-url> --actions like,reply,connect --reply-text "Good point." --connect-note "I liked your perspective here." --max-commenters 25 --duration 3m  # Read a post's commenters, then like, reply, or connect (paid, WAB writes)

# Account creation (wab-only, flagged: linkedinAccountCreationEnabled)
wonda linkedin signup --persona <name> --random                                     # Create a brand-new account end-to-end
wonda linkedin signup --persona <name> --email <addr> --first-name Ada --last-name Lovelace --password <pw>
wonda linkedin signup --persona <name> --job-title "Engineer" --company "Acme"       # Profile stage with employment (default: student path)
wonda linkedin signup --persona <name> --resume code --email <addr>                  # Resume after a manual step

分页命令支持:-n <count>、--start、--all、--max-pages、--delay <ms>。

如果成员在 LinkedIn 的 Contact info 中公开了相关字段,wonda linkedin profile 会额外包含 emails、websites、phone 和 twitter 字段。联系信息读取使用与个人资料读取相同的已登录 Voyager Cookie 和 CSRF 路径;如果信息被隐藏或受到速率限制,则会尽力读取。其效果等同于手动打开 Contact info 覆盖层。它不会推断、补充、持久化或批量采集联系人。 LinkedIn 成员身份解析: wonda linkedin resolve <id>... 接受裸 ACoAA... fsd 个人资料 ID,以及 urn:li:fsd_profile: 和 urn:li:fs_miniProfile: 包装形式。每个唯一的缓存未命中项都会执行一次仅使用 Cookie 的 Voyager 读取,并在所选账户下将成功结果缓存 30 天。--no-cache 会跳过持久缓存的读取和写入,但仍会在本次调用中去重。数字形式的 urn:li:member:<id> 会被拒绝,因为 LinkedIn 的身份验证网页重定向会保留数字 ID,且没有可用的稳定 Voyager 映射端点。conversations --resolve 和 messages --resolve 使用同一缓存,且仅填充已有的空白 vanityName 字段;不使用 --resolve 时,输出保持不变。

wonda linkedin profile 还会返回 education(包含 {school, degree, fieldOfStudy, startYear, endYear} 的列表,endYear 为 0 表示仍在就读)、yearsOfExperience(职业跨度年数,根据最早的有日期记录计算;没有记录时为 0)、完整的 experiences 工作经历(每项包含 {title, companyName, companyUrn, companyUniversalName, startYear, startMonth, endYear, location},endYear 为 0 表示当前职位),以及采用相同结构的当前职位 currentCompany。这些信息通过与个人资料其他内容相同的已登录 Voyager Cookie/CSRF 路径读取;如果信息被隐藏或受到速率限制,则尽力返回。

LinkedIn 个人资料访问预热: wonda linkedin visit <vanity-or-url> --account <name> 仅适用于 WAB,且与 wonda linkedin profile 有意分开。profile 是隐蔽的数据读取,不会触发“有人查看了你的个人资料”通知。visit 会在 persona 浏览器中打开真实的 /in/<vanity>/ 页面,默认停留约 6-20 秒;除非设置了 --no-scroll,否则还会轻轻滚动页面一次,并返回 { ok, status, profile, dwellMs, scrolled }。LinkedIn 的私密或匿名个人资料浏览设置可能会阻止向目标用户发送通知。

LinkedIn 账户创建: wonda linkedin signup 会创建全新的 LinkedIn 账户:生成一个一次性邮箱(或使用 --email),在有界面的 WAB 窗口中完成注册流程(邮箱和密码、姓名、通过邮件发送的验证码、个人资料),从收件箱获取验证码 PIN,然后绑定 persona 并同步 Cookie,使 LinkedIn 的读取和写入通过新账户进行。此功能受 linkedinAccountCreationEnabled 标志限制(由服务端评估预检:GET /linkedin/signup/enabled)。请先为 persona 绑定移动网络或住宅代理(wonda wab config set <persona> proxy_url socks5://...):LinkedIn 对数据中心 IP 注册账户的影子封禁比 Reddit 更严厉。LinkedIn 经常会插入验证码或“安全验证”谜题,流程无法自动通过;如果找不到某个字段,流程会暂停并将窗口停留在该页面,请手动完成,然后使用 --resume <step>(account|name|code|profile|persist)重新运行。成功后会打印 {name, email, password, persona, account},以及可直接粘贴的 "LinkedIn logins" vault 的 op item create 代码块。

连接请求模式: connect 命令有两种传输方式:

  • --via cookies(API): 使用指纹缓解措施(访问个人资料、预热抽屉、连接)的 Voyager REST API。速度快(约 3 秒),支持通过 customMessage 添加备注。
  • --via wab: 通过账户的 persona Chromium(自动启动)使用 DOM 调度,实现完全隐蔽。指纹识别风险为零。速度较慢(约 10 秒),但完全安全。需要额外保护时使用。只需通过 wonda wab install 安装一次隐蔽浏览器和 Chromium(约 315 MB,重复执行无影响)。persona 会复用其位于 ~/.wonda/wab/personas/<persona>/profile 下的持久化配置文件。Cookie 存储在 ~/.wonda/linkedin-cookies/<account>.json 中,并通过 account-bindings.json 绑定到 persona;使用 wonda linkedin auth set --account <name> 轮换 Cookie 时,如果 Chromium 正在运行,新 Cookie 会推送到其中。 连接请求 JSON 失败: 本地 WAB 连接失败时会以非零状态退出,并向 stderr 写入结构化 JSON 错误。对于真正的一次性拒绝,error.code 保持为 send-rejected。每周邀请次数达到上限或发送静默丢弃时,使用 send-throttled,机器可读原因分别为 weekly_invitation_limit 或 silent_drop;HTTP 429 仍使用 blocked:rate-limit,原因是 http_429。连接失败会包含 throttled,界面中可见的失败会在 detail 中包含原始提示消息。使用 JSON 输出时,本地 --hard 操作预算触发限制会在 stdout 上输出 error: "hard-rate-limit"、throttled: true 和 reason: "local_hard_limit",同时保留现有的 stderr 提示语。云端包装的失败会保留现有外层 HTTP 状态、error.code 和 error.reason;原始连接令牌和原因会作为额外字段 error.actionCode 和 error.actionReason 输出。

LinkedIn InMail: wonda linkedin inmail <vanity-or-url> --message <body> [--subject <subject>] [--spend-credit] [--dry-run] 仅通过 WAB 操作 LinkedIn 原生 InMail 撰写器。它不是 connect,也不是 send-message;对于一级联系人,会拒绝操作并提示使用 wonda linkedin send-message。Open Profile / 免费 InMail 无需确认即可发送。如果 LinkedIn 表示将消耗 1 个 InMail 积分,则命令会以 sent:false 停止,除非提供 --spend-credit(已弃用的别名 --yes-consume-credit 仍可使用)。--dry-run 会填写撰写器,并在点击 Send 前停止。

LinkedIn Recruiter Lite(Wonda 1.61.0+): wonda linkedin recruiter 通过选定的 LinkedIn 账号/身份提供 6 个命令,并要求该账号拥有 Recruiter Lite 席位。现有已保存查询的 Cookie 搜索、列表、有限范围的原生打开和分页操作均已通过常规 CLI 验证。在一个目标候选人上进行的个人资料比较中,Cookie 和 WAB 传输均保留了 7 段工作经历、2 条教育记录和 42 项技能;最终 Cookie 个人资料以退出码 0 返回,且 partial:false。通过匹配原生参数编码和 Recruiter 应用上下文,使用现有 Cookie 解决了观察到的请求失败。已在关闭提醒的情况下,针对一项真实目标保存记录观察到原生 WAB 保存/列表/打开操作。Cookie 保存使用经检查的原生客户端契约,包括重复项/容量检查、单次创建尝试和已保存搜索 ID 验证,但仅有夹具覆盖;未为实时测试创建额外记录。尚未确认筛选器/运算符的全面一致性,且原生打开操作不接受筛选器覆盖。

Command默认传输方式行为
recruiter filters [filter-type] [query]cookies不带参数时返回记录的 26 项控件目录,不会联系 LinkedIn;指定值时使用映射的 facet/typeahead 路由。WAB 读取已渲染的控件
recruiter search [keywords]cookies返回有限数量的候选人卡片、实际生效的筛选条件和后续结果元数据
recruiter profile <candidate-ref...>cookies返回完整的公开个人资料版块,以及可用的各职位描述
recruiter saved-searchescookies列出原生记录、项目/所有者身份和提醒状态,不打开搜索
recruiter save-search <name> [keywords]wabWAB 填写原生表单、提交一次并验证是否持久保存;提醒默认关闭
recruiter open-saved-search <id-or-exact-name>wab恢复原生的项目范围搜索;返回已保存记录及有限数量的搜索结果

--via cookies 表示已通过身份验证的内部 Recruiter API;--via wab 表示实际的浏览器导航、已渲染的 DOM 和可信输入。两者都不会执行身份验证探测、自动会话刷新、重试或传输方式回退。最初的 cookie 搜索 HTTP 500 错误已通过修正原生参数序列化解决;之后的有限范围搜索已通过。匹配原生 Recruiter 应用上下文后,也恢复了所请求的个人资料技能。请求的版块缺失时,仍会返回部分结果。不要通过静默更改传输方式来绕过错误。

搜索支持可重复使用的 --filter TYPE=VALUE、--exclude-filter TYPE=VALUE、--range-filter TYPE=MIN:MAX、--toggle TYPE[=true|false]、--filters-json <JSON-or-local-file> 和捕获的 --search-url,包括原生项目/已保存搜索 GET URL。Cookie 原生 URL 重放会保留项目/所有者上下文,目前不接受筛选条件覆盖。结构化子句支持 operator: "require"、作用域和原始观测值。WAB 会在导航前拒绝未映射的原始字段。--interactive --via wab 会暂停操作,供其配置实际搜索;不会保存原生搜索。目录覆盖范围并不意味着每项依赖或运算符都已实现在线等效支持。 --count 表示每个逻辑页面的结果数,而非总上限。默认值为 10 个结果 × 10 页;除非指定 --max-pages,否则 --all 最多允许 100 页。对于范围较小的预期操作,请明确指定页数上限。即使返回的结果较少,Recruiter 的物理 UI 页面目前也包含 25 个结果。--delay 设置每次 cookie 请求之间的最小间隔,包括准备阶段的集合/项目/输入提示读取,以及 WAB 交互之前的间隔。它不会降低现有的 cookie 节流限制。--max-pages 也会限制物理 WAB 页数,因此距离较远的 --start 可能在到达之前就失败。--details full 会增加个人资料读取,--max-profiles 默认值为 250。--override-max-profiles 允许请求高于 250 的上限;请求的 --max-profiles 仍会限制访问次数,同时仍会遵守平台错误和请求节奏控制。这些值是 Wonda 的控制参数,并非 LinkedIn 批准的配额。

仅使用已捕获的不透明候选人引用或实际的 /talent/profile/... 链接。只有在公开 /in/... URL 时才会输出,并附带来源信息。候选人输出保留当前/过往职位、多行描述、教育经历、技能、可用的可选部分,以及每个部分的状态,例如完整、部分、不可用和未观察到。缺失字段不代表该部分为空且完整。页面/读取失败时,仍会将有用结果输出到 stdout,并附带 partial/errors,且以非零状态退出。--csv 会生成 Wonda CSV,并在带引号的 JSON 单元格中保留结构化履历;无需使用 LinkedIn 原生导出。CSV 的 partial 同时包含候选人和结果失败;extraction 保留候选人特定状态,而 result_partial 和 JSON result_errors 会在每行保留整体结果。record_type=candidate 用于标识候选人行;如果结果失败且没有候选人,则会输出一行 record_type=result,不包含候选人身份信息。类似公式的 CSV 文本会在开头添加带引号的制表符,以便导入电子表格;该制表符会保留在 CSV 数据中,而 JSON 会保留原始文本。--no-cache 会跳过个人资料缓存复用。部分个人资料、显式凭据以及未知/过期的席位上下文不会复用缓存条目。席位/合同命名空间来自现有的本地 Recruiter 会话 cookie,不会发送身份验证请求;上下文变更后不会缓存。独立 WAB 缓存复用已通过常规 CLI 验证。

原生项目标志为 --recruiter-project(WAB 使用精确名称,cookie 使用 ID 或精确名称)和 --new-recruiter-project;全局 --project 仍表示 Wonda 项目上下文。Cookie 项目查找优先匹配精确名称,包括数字名称;完整捕获的项目 URN 可无歧义地选择 ID。默认关闭提醒。已在预期的真实记录上观察到 WAB 保存/打开行为。未经验证的保存结果不得自动重试。viewedMarkerChanged:null 表示原生 GET 标记效果未知。切勿为了验证而在真实帐户中创建一次性记录或触发容量失败。 本地 MCP 和 twin 负载共用全部六种命令契约,显式选择传输方式,并限制参数范围。工具搜索默认每页 25 个、共 1 页,请求候选项上限为 375 个;all:true 会扩展至最多 15 页,但仍受此候选项上限约束,显式设置的 maxPages 始终优先。完整资料输入/补充信息的上限为 10 个。对于有意等待时间超过 280 秒同步预算(其中预留 40 秒用于处理)的负载,会在分发前拒绝;较长操作请使用较小批次或本地 CLI。请求的延迟绝不会缩短。工具接受 JSON 筛选条件内容,而非本地文件路径。要求使用 Wonda 1.61.0 或更高版本。CLI --engine local|cloud|auto 使用现有引擎解析器和 twin 分发。本地 Cookie 覆盖值无法发送至云端;--interactive 和 --override-max-profiles 需要在本地执行。Runner/本地 MCP 命令会固定使用本地引擎,以防重新分发。部分托管结果会保留标准输出,并返回非零退出码。

LinkedIn InMail 额度余额: wonda linkedin inmail-credits 为只读命令,通过 Cookie 传输从 Sales Navigator 额度授予端点返回该席位剩余的 InMail 额度余额,字段为 remaining(另含授予类型和 ID)。它不会发送任何内容,也不会消耗额度;请在使用 wonda linkedin inmail --spend-credit 前用它进行规划。账号必须有有效的 Sales Navigator 席位;仅有旗舰版 Premium 的账号无法通过此方式读取余额。

LinkedIn 公开个人资料补充信息: wonda linkedin enrich <profile-url-or-vanity...> 默认使用 --via cookies,一次处理一个个人资料,走本地已登录个人资料读取路径,复用 _artifacts/linkedin-cache,在缓存未命中之间加入随机延迟,并在收到 429 类速率限制信号时中止。直接运行时,输入超过 25 个会被拒绝。linkedin_enrich 工具(本地 MCP 和 twin 操作路由)将批量 targets 调用上限设为 10:该路径与调用方共用更严格的截止时间(Go API 客户端的 300s 请求取消超时,以及其他同步 HTTP 调用),运行 25 个个人资料可能会超时。--via cookies 和 --via wab 都会在返回的个人资料中包含每个个人资料的教育经历(学校、学位、专业、入学年份、毕业年份)和推算出的 yearsOfExperience,但教育经历的获取为尽力而为:如果此可选请求发生暂时性故障(速率限制除外),仍会成功返回补充信息结果,只是不包含教育经历字段,并按原样缓存该结果。缓存命中时会按原样返回;由未获取教育经历且共用此缓存的命令(enrich-engagers、search-posts 作者个人资料)、此更改前的 enrich,或此前尽力获取失败所写入的条目都不含教育经历,因此需要教育经历时请传入 --force-refresh。enrich-engagers 不会请求教育经历,因此每位互动者的个人资料读取次数不变。付费公开资料补充请使用 --via public:通过 POST /api/v1/scrape/linkedin-profiles 发起请求,并轮询 GET /api/v1/scrape/linkedin-profiles/{taskId} 直至完成,除非设置了 --no-wait。使用 wonda scrape cancel <taskId> 取消正在运行的付费抓取。公开模式支持 --force-refresh、--timeout 10m、--idempotency-key 和 --output json|table。单份个人资料的 wonda linkedin profile --via public 路径使用相同的付费接口,也支持 --force-refresh、--timeout 和 --idempotency-key。

  • --via wab 会通过 persona 的 Wonda Automation Browser 会话运行相同批次:每次个人资料读取都在已登录的浏览器中执行(使用真实浏览器指纹,不会遇到扁平存储的陈旧问题)。与 --via cookies 相同,最多输入 25 个,使用相同的请求间隔、缓存,以及教育经历/yearsOfExperience 字段。适用于 Sales Navigator 导出后的批量处理,或 Cookie 读取持续失败的情况。 LinkedIn 已发送邀请追踪: wonda linkedin sent-invitations 为只读命令,默认使用 --via cookies。该命令会列出当前待处理的已发送邀请,并默认将其与本地 WAB connect 审计记录核对,将经过审计的目标标记为 accepted、pending、withdrawn 或 unknown;传入 --reconcile=false 可获取原始分页待处理列表,传入 --no-connection-check 可跳过逐个目标的连接状态读取。--via wab 会通过账号身份执行相同的读取操作。LinkedIn 的已发送列表 Voyager 端点目前变动频繁,因此该命令会先尝试可分页的 Voyager 变体,再回退到只读的已发送邀请管理页面。结果始终会报告 complete、fetched、knownTotal 和 source。只有在确认清单完整时,complete 才为 true;fetched 统计返回的不同待处理行数;knownTotal 是 LinkedIn 标示的总数,若缺失或不一致则为 null;source 为 voyager 或 html。HTML 回退结果还会报告 fetchCap,即渲染后的 HTML 行数上限;未使用 HTML 时不包含此字段。清单不完整时,仍会返回可用行,并将 complete 设为 false。若目标经过审计但不在不完整的清单中,且连接检查已禁用或失败,该目标会标记为 unknown,绝不会推断为已撤回。acceptRate 不包含状态未知的行。不支持 --via public 和 --via api。

LinkedIn 连接状态批量查询: wonda linkedin connection-status <inputs...> 会严格按照原始顺序,为每个输入返回一条结果。每一行都包含精确的原始 input。查找失败时会标记为 status: "error",并包含 error,而不是直接丢弃。单个输入仍使用对象结构;多个输入仍使用数组结构。单次查找失败时,会在 stdout 中添加带有错误标记的对象,同时保留现有的 stderr 错误和非零退出码。

互动者信息补充: wonda linkedin enrich-engagers --activity-id <id> 会抓取点赞者(并可通过 --comments 选择抓取评论者),然后获取每位互动者的个人资料、当前雇主和公司页面信息,最终输出一个以 vanity 为键的合并 JSON 文档;每位互动者都包含 profile 和 currentEmployer(行业、员工人数、总部、描述、员工数量)信息块。使用 --company-detail=false 可跳过公司页面查询,仅保留内嵌的雇主身份信息(name、urn、universalName)。使用 --max-profiles N 可限制批量数量(默认 250;除非设置 --override-max-profiles,否则上限为 250),使用 --out file.json 可写入磁盘。--profile-source cookies|public 仅控制逐个个人资料的详细信息补充;互动者收集仍使用已登录的 LinkedIn 访问权限。

如需对帖文互动者进行 ICP 资格评估,请运行 wonda skill get linkedin-icp-qualify。

Instagram

一流的平台,通过 --via 选择三种传输方式,正当性梯度与其他平台相同:

  • --via api — 通过已连接的 OAuth 账户(--connection)调用官方 Graph API。符合 ToS,用于发布内容。
  • --via cookies — 通过本地 Cookie --account 调用私有移动 API。用于读取(已保存的帖子、评论)。
  • --via wab — 通过账户的 Wonda Automation Browser persona 读取浏览器 DOM。用于原生个人资料/帖子/发现内容读取,以及 comment 写入。

传输方式按操作提供能力:saved 和 comments 仅支持 Cookie(没有对应的 Graph 端点);post --media/carousel 通过 API 发布;而 post <URL-or-code>、user、user-posts、search、home、following 和 comment 使用 WAB。两种身份各不相同:--account/--sessionid = 本地 Cookie 身份;--connection = OAuth instagram_account UUID。对于 --via wab,persona 会根据 --account 自动派生(也可以直接传入 --persona);WAB 会在启动 Chromium 时,将绑定账户的 sessionid(以及 ds_user_id)注入 Cookie jar。

⚠️ 与其他平台一样,请注意防范反欺诈机制:不要探测刚粘贴的 Cookie。 新 sessionid 的第一个请求应当就是你想执行的操作。Instagram 会标记来自新 IP/进程、使用刚交付的会话所产生的突发活动。

# Auth setup — local cookie identity (run `wonda instagram auth --help` for details)
wonda instagram auth set --sessionid <value>                # Just the sessionid cookie (simplest)
wonda instagram auth set --cookies "$(pbpaste)"             # Full DevTools cookie: header (also captures ds_user_id)
wonda instagram auth set --account <name> --sessionid <v>   # Multi-account
wonda instagram auth set --account <name> --sessionid <v> --persona <persona>  # Also bind to a WAB persona

# Read (cookies)
wonda instagram saved                                       # Your saved posts (--all to walk all pages)
wonda instagram saved --jq '.posts[] | {authorHandle, url}' # Project fields out of the result
wonda instagram comments https://instagram.com/reel/<code>/ # A post/reel's comments (--all to walk all pages)
wonda instagram comments <code> --jq '.comments[] | {authorHandle, text}'  # Bare shortcode also works

# Publish (--via api, default — the official Graph API via your connected account)
wonda instagram post --media <media-id> --caption "Hello"   # Single image/reel
wonda instagram post --media <id> --connection <ig-uuid>    # Pick the connected account explicitly
wonda instagram carousel --media <id1> --media <id2>        # 2-10 image carousel

# Comment on a reel (--via wab only — drives the inline composer in the WAB)
wonda instagram comment https://instagram.com/reel/<code>/ "Great reel!" --persona my-account
wonda instagram comment <code> "Love this" --persona my-account   # Bare shortcode also works

# Feed-engage (--via wab only: scroll the home feed and like target authors' posts)
wonda instagram feed-engage --authors "a,b" --duration 5m --persona my-account  # Scroll the feed and like posts from these authors (wab-only)

--account 会选择 ~/.wonda/instagram-cookies/<account>.json 下的 Cookie 文件。对于 saved,轮播帖子会纳入每个子项的媒体 URL(每个项目的 URL 优先选视频,而非图片);分页使用 max_id 游标(--cursor、--all、--max-pages、--delay <ms>)。comments 接受 /p/<code>/ 或 /reel/<code>/ URL(或不带前缀的短代码),会在本地将其解码为数字媒体 ID,然后继续分页使用相同的 max_id 游标;结果包含每条评论的 id、text、authorHandle、authorName、createdAt、likeCount、replyCount,以及父媒体的总 commentCount。发布内容时,wonda instagram post --via api 和 wonda publish instagram 共用同一条 Graph API 路径。comment(写入)接受 /reel/<code>/ 或 /p/<code>/ URL(或不带前缀的短代码)以及文本,并且仅支持 wab:如有需要,会自动启动该 persona 的 WAB,在内嵌编辑框中输入并提交,然后向 ~/.wonda/wab/audit.jsonl 写入一条 comment 审计记录(失败时会触发 wab_action_failed 遥测并生成失败诊断包)。

Instagram 和 TikTok 原生浏览器读取

使用现有的、已登录的本地 burner persona。这些读取操作默认使用 --via wab;显式指定 --via cookies 或 api 会失败,因为原生会话状态和浏览器请求提供了当前读取所需的契约。--persona 用于选择确切的浏览器配置文件,也可以通过 --account 派生 persona。这些命令不会登录、关注、点赞、评论或发送消息。遇到登录墙、验证关卡、CAPTCHA 或速率限制响应时,命令会停止并报错,同时生成诊断包。下次尝试前,请在同一个 persona 中完成所需的登录/验证。

wonda instagram user casey.aicreates --persona ig-burner
wonda instagram user-posts gptars.ai --persona ig-burner --limit 12
wonda instagram post https://www.instagram.com/reel/ABC123/ --persona ig-burner
wonda instagram post ABC123 --persona ig-burner --download-dir ./originals
wonda instagram search "desk robot" --type users --persona ig-burner
wonda instagram search deskrobot --type hashtags --persona ig-burner
wonda instagram following gptars.ai --persona ig-burner --limit 20
wonda instagram home --persona ig-burner --limit 5
wonda tiktok user gptars --persona tiktok-burner
wonda tiktok user-videos gptars --persona tiktok-burner --limit 12
wonda tiktok video https://www.tiktok.com/@gptars/video/7692098404066888973 --persona tiktok-burner --download-dir ./originals
wonda tiktok search "diy desk robot" --type videos --persona tiktok-burner
wonda tiktok search "diy desk robot" --sort date --posted month --persona tiktok-burner
wonda tiktok search "diy desk robot" --type users --persona tiktok-burner
wonda tiktok following gptars --persona tiktok-burner
wonda tiktok home --persona tiktok-burner --limit 5

个人资料会返回 handle、name、bio、followerCount、followingCount、postCount、isPrivate 和规范 URL。Instagram 帖子列表返回 posts;TikTok 列表返回 videos。项目包含 id、url、authorHandle、authorName、精确到 UTC 的 postedAt、caption、mediaType、mediaUrls、videoUrl、thumbnail 以及可用的互动数。Instagram 还包含 taggedUsers 和 mentionedUsers;TikTok 还包含提及对象和 shareCount。缺失的指标为 null,计数为零时仍保留为零。原生个人资料的排序可能包含置顶帖子;两个平台都会在项目中提供 isPinned。

读取 Instagram 个人资料时,会将原生简介中的“更多”控件展开一次,再提取完整文本,以保留创作者署名和较短的简介。如果未能在限定等待时间内完成展开,读取就会失败,而不会将折叠的预览文本作为完整简介返回。 Instagram 的 post 和 user-posts 命令会从作者原生 Reels 网格中补充缺失的 Reels 播放量。viewCount 是 play_count、ig_play_count 或 view_count 中的精确整数,绝不会使用经过取整的网格标签;补充播放量后,viewCountSource 会标明所用的 Reels 字段。这样可以保留每条帖子的时间戳、说明文字和原始列表顺序。单条帖子最多进行 3 轮 Reels 补充,列表补充受 --max-pages 限制。超出此范围的不可用或较旧播放量会保留为 null。

TikTok 视频搜索支持 --sort relevance|date|likes 和 --posted all|24h|week|month|3m|6m。当前原生网页搜索不提供日期或排序控制,因此这些标志会在有界的原生结果窗口内由客户端筛选和排序;设置任一标志时,默认进行 6 轮原生查询。--max-pages 可将此上限提高到 10。时间范围按精确的 UTC 时间戳和 1、7、30、90、180 天计算。JSON 中的 filtering 会报告 appliedBy: "client"、scannedCount、matchedCount、截止时间/当前时间以及 windowHasMore;这并不代表对所有符合条件的 TikTok 视频进行全局排序。若要检查更大的窗口,请提高上限并重新开始读取。筛选后的游标必须与相同的标志和页面上限一起使用,并会保留原始截止时间。用户搜索不接受这些仅适用于视频的标志。

列表默认包含 12 个项目,并进行 3 轮原生分页/滚动。--limit 接受 1–100,--max-pages 接受 1–10。用户列表、关注列表和搜索结果在可能还有更多结果时会返回 cursor:仅可对相同的命令、目标和搜索类型复用该游标。它会在 --max-pages 范围内重放原生页面,从最后一项之后继续读取。如果锚点位置更靠后,请提高此上限。找不到锚点时会报错。个性化首页/For You 信息流没有可恢复的游标。所有读取都会使用现有的节流记录;搜索的每日安全/最高默认次数为 25/50 次,由 --hard 强制执行。私密或隐藏的关注列表无法访问。

对单条帖子/视频使用 --download-dir,会逐字节保存平台提供的最佳视频,或轮播中的每张图片/视频,不会进行转码。JSON 中的 downloads 回执包含绝对路径、字节长度、内容类型和 SHA-256。已有目标文件会被保留;签名 URL 可能过期,因此重试下载前请刷新帖子。每个文件 1 GiB 的上限可防止无界下载。

此版本中的这些新读取功能仅限本地 CLI 命令。它们明确不纳入托管 Twin 和 MCP 操作注册:这些功能依赖本地原生配置文件状态,而可恢复的浏览器游标和本地文件下载没有托管操作契约。请直接运行 CLI。标签搜索会返回匹配的标签;由于网站的关键词/探索页面不提供稳定的热门/最新排序契约,因此不会提供标签的热门/最新帖子信息流。

Reddit

Reddit 会根据命令类型固定传输方式,因此在这里基本无法自行选择 --via:

  • 读取(搜索、subreddit、信息流、用户、user-posts、user-comments、帖子、热门内容、首页、已保存内容)会通过带 Chrome 指纹的 Go HTTP 客户端直接执行(速度快,p50 约为 700 ms)。仅使用 Cookie。读取命令不支持 --via wab,使用时会报错。
  • 写入(投票、评论、订阅、保存、取消保存、删除,以及 subreddit 的 submit)会通过账户的 Wonda Automation Browser 分发,以便 shreddit GraphQL mutation 携带真实浏览器信号。仅支持 WAB。对这些命令使用 --via cookies 会报错。
  • 向个人资料发布自帖(u_<handle> / u/<handle>)或发布链接帖仅通过 tls-client(Cookie)执行。这些操作不支持 --via wab(没有 DOM 提交 URL),因此 --dry-run(仅限 DOM)也不适用于它们。

--account 会选择 ~/.wonda/reddit-cookies/ 下的 Cookie 文件(写入时也会选择该账户自动推导的 persona)。这里无需传入 persona。

⚠️ 关于刚粘贴的 Cookie 的反欺诈提醒。 wonda reddit auth check 是安全的(它只会在本地解码 JWT 的 exp),但你首次使用新 Cookie 执行读取或写入操作时,都会通过你的 IP/进程调用 Reddit 的 API。如果这些 Cookie 上次是在别处使用的(不同的机器、不同的国家/地区),Reddit 的反欺诈机制会触发会话被盗用启发式检测,并可能强制注销这些 Cookie。建议流程:粘贴 Cookie 后,直接执行用户需要的操作。切勿先进行「让我先检查一下能不能用」的往返操作。

# Auth setup (run `wonda reddit auth --help` for details)
wonda reddit auth set --cookies "$(pbpaste)"                         # Paste full DevTools cookie: header
wonda reddit auth set --account <name>-1 --cookies "$(pbpaste)"      # Multi-account
wonda reddit auth set --account <name>-1 --from-keychain             # Opt-in: read from browser Keychain
wonda reddit auth check

# Read (direct tls-client, --account picks the session for logged-in views)
wonda reddit search "AI video" --sort top --time week   # Search posts (sort: relevance, hot, top, new, comments)
wonda reddit subreddit marketing                        # Subreddit info
wonda reddit rules marketing                            # Subreddit posting rules (+ site-wide rules)
wonda reddit feed marketing --sort hot                  # Subreddit posts (sort: hot, new, top, rising)
wonda reddit comments marketing                         # Newest comments across a subreddit (find reply opportunities)
wonda reddit user spez                                  # User profile
wonda reddit user-posts spez --sort top                 # User's posts
wonda reddit user-comments spez                         # User's comments
wonda reddit post <id-or-url> -n 50                     # Post with comments
wonda reddit analytics <id-or-url>                      # Owner viewCount plus public score, upvoteRatio, commentCount
wonda reddit trending --sort hot                        # Popular/trending posts
wonda reddit home --sort best                           # Your home feed (requires auth)
wonda reddit saved                                      # Your saved posts + comments (requires auth; --all to walk all pages)
wonda reddit whoami                                     # Your own account identity: username + id + karma (requires auth; alias: me)
wonda reddit inbox                                      # Classic notifications: replies to your posts/comments, mentions, old PMs (requires auth)
wonda reddit inbox --unread                             # Only unread; --type mentions for mentions only

# Write (wab-only via the account's persona; --account selects the identity)
wonda reddit submit marketing --title "Great tool" --text "Check this..." --account <name>-1   # Subreddit text post (DOM)
wonda reddit submit marketing --title "..." --text "..." --flair "Discussion" --account <name>-1 # Subreddit text post with flair
wonda reddit submit test --title "Native image with body" --media ./image.png --text "Optional retained body" --flair "Discussion" --account <test-name>
wonda reddit submit test --title "Native video with body" --media ./video.mp4 --text "Optional retained body" --account <test-name>
wonda reddit submit u_<your-handle> --title "..." --text "..." --account <name>-1               # Profile self-post (tls-client / cookies only)
wonda reddit submit marketing --title "..." --url "https://..." --account <name>-1              # Link post (tls-client / cookies only)
wonda reddit comment t3_<post-id> --text "Nice post!" --account <name>-1
wonda reddit comment t1_<comment-id> --text "..." --post-id t3_<post-id> --account <name>-1 # Nested reply (needs parent post-id)
wonda reddit vote <fullname> --up --account <name>-1     # Upvote (--down, --unvote)
wonda reddit vote t1_<comment-id> --up --post-id t3_<post-id> --account <name>-1
wonda reddit subscribe marketing --account <name>-1      # Subscribe (--unsub to unsubscribe)
wonda reddit save <fullname> --account <name>-1          # Save a post or comment (--post-id for t1_*)
wonda reddit unsave <fullname> --account <name>-1
wonda reddit delete <fullname> --account <name>-1        # Delete your own post or comment
wonda reddit feed-engage --authors "a,b" --duration 5m   # Scroll the feed and upvote posts from these authors (wab-only)
wonda reddit feed-engage --keywords "ai video,ugc ads" --subreddits SaaS,marketing --reply --max-reply 3  # Monitor scoped searches, gate relevance, comment via WAB

# Account creation (wab-only, flagged: redditAccountCreationEnabled)
wonda reddit signup --persona <name> --random                                       # Create a brand-new account end-to-end
wonda reddit signup --persona <name> --email <addr> --username <handle> --password <pw>
wonda reddit signup --persona <name> --resume credentials                           # Resume after a manual step

如果用户在公开的 About 文本中发布了明确的联系方式,wonda reddit user 会额外返回 emails 和 links 字段。这些字段为只读,与手动查看个人资料的效果相同。不涉及推断电子邮件地址、数据补充、存储或 DOM 抓取。

在 subreddit 的 comment 或 submit 命令中添加 --dry-run,即可在编辑框中输入内容,但不会点击 Post(适用于内容审核)。此功能仅操作 DOM,因此不适用于个人资料的自发帖子或链接帖子。对于 subreddit 帖子,传入 --flair "<label>" 可在编辑框中选择帖子 Flair。Flair 标签会忽略大小写并规范化空白字符进行匹配:先精确匹配标签,再回退到唯一的包含匹配。选择器会展开 View all flairs,将所需行滚动到页脚上方,并在发布前验证已选定的 Flair ID 或精确标签。如果 subreddit 要求设置 Flair 但未提供,或请求的 Flair 不存在,命令会失败并显示可用的 Flair 标签。个人资料的自发帖子或 --url 链接帖子不支持 --flair。原生图片/视频帖子支持使用 --media,并可选带上 --text 正文。对于文本、图片和视频帖子,--text 使用 Markdown:引用块、链接、强调和列表都会渲染为格式。命令会将正文编辑框切换为原生 Markdown 编辑器,在不额外添加前导空行的情况下填入内容,并在提交前验证保留的 Markdown 完全一致。仅媒体和仅文本的提交仍受支持;--url 仍不能与文本或媒体同时使用。

wonda reddit signup 用于创建全新的 Reddit 账号:它会生成一次性邮箱(或使用 --email),在显示浏览器窗口的 WAB 中驱动 5 阶段注册表单(电子邮件、邮件验证码、用户名和密码、年龄、兴趣),从收件箱主题行获取验证码,然后绑定该身份并同步 Cookie,使 Reddit 的读写操作通过新账号进行。此功能受 redditAccountCreationEnabled 标志控制(服务器评估的预检:GET /reddit/signup/enabled)。请先为该身份绑定移动网络或住宅代理(wonda wab config set <persona> proxy_url socks5://...):Reddit 会对使用数据中心 IP 创建的账号实施影子封禁。如果无法定位某个字段,流程会暂停并将窗口停留在该页面;请手动完成,然后使用 --resume <step> 重新运行。成功后会打印 {username, email, password, persona},以及可直接粘贴到 "Reddit logins" 密钥库中的 op item create 命令块。

支持分页的命令包括:-n <count>、--after <cursor>、--all、--max-pages、--delay <ms>。 Feed-engage 作者模式(wonda {linkedin,x,reddit,instagram} feed-engage):像真人一样滚动浏览首页信息流,只与滚动经过的目标作者帖子互动。在 Reddit 上,互动方式是点赞,在其他平台上则是点喜欢。此模式仅支持 WAB(它会通过账号的人设实时滚动浏览器并点击,因此没有 Cookie 路径),而且是机会式的:它不会打开个人资料或进行搜索,只会浏览信息流,并在目标作者的帖子出现时采取操作。使用 --authors "alice,bob"(逗号分隔的句柄/个性网址/用户名,开头的 @ 和 u/ 会被移除)或 --authors-file <path>(每行一个作者,仅限本地使用)传入目标。--duration 限制实际浏览时长(例如 5m、90s,默认为 2m),--max-engage 限制成功点喜欢/点赞的次数(默认为 8);任一限制先达到都会停止运行。操作节奏贴近真人(平滑滚动、随机停留、光标移动带有抖动),因此请让它运行满设定时长,不要期待立刻得到结果。

LinkedIn 作者模式还可以通过 --engage-comments 选择对评论做出回应:默认只回应来自 --authors 的评论;--engage-comments-from any 会纳入所有可见评论;--max-comment-engage 限制每篇已互动帖子上的评论回应次数(默认为 3)。

LinkedIn 评论者互动(wonda linkedin engage-commenters):读取一篇 LinkedIn 帖子下的评论者,然后按顺序执行所选的逐评论者操作:like、reply、connect。使用 --post <activity-id|urn|url> 传入帖子。--actions 接受 like,reply,connect,默认为 like;选择 reply 时必须提供 --reply-text;--connect-note 为可选项;--max-commenters 默认为 25;--duration 默认为 3m;--dry-run 会解析目标并打开控件/编辑框,但不会提交写入操作。访问等级:付费/WAB。传输方式:读取评论者使用现有的 LinkedIn DOM 评论路径;所有写入操作均使用 WAB DOM 原语。

Feed-engage 监控模式(wonda {linkedin,x,reddit} feed-engage --keywords ...):运行一次有时限的关键词/意图监控,使用 /text/generate 为未查看的候选内容评分,并可选择使用 /text/generate 生成符合人设的回复。--keywords 会启用监控模式,且不能与 --authors 和 --authors-file 同时使用。Reddit 支持使用 --subreddits SaaS,marketing 限定搜索范围。不使用 --reply 时,监控模式为只读,并会输出候选内容及相关性判定。使用 --reply --dry-run 时,会生成回复文本但不发布,也不会更改记录账本。使用 --reply 时,仅通过 DOM/WAB 写入器发布:Reddit 评论编辑框、X 回复编辑框和 LinkedIn 评论编辑框。读取操作会在可用时使用 Cookie/tls-client:Reddit 搜索和 X 搜索使用平台客户端;LinkedIn 内容搜索使用现有的 WAB DOM search-posts 流程,因为通过 Cookie API 进行 LinkedIn 内容搜索并不可靠。安全控制:--max-scan(默认为 50)、--relevance-threshold(默认为 0.7)、--max-reply(默认为 3)、--per-day-cap(默认为 8),以及位于 ~/.wonda/reply-ledger/ 下的持久化去重记录账本。生成的公开回复会经过后处理,以移除长破折号。Instagram 不支持监控模式。

跨平台私信支持范围
平台读取收件箱读取对话在现有会话中发送发起对话或陌生人私信
LinkedIn是是是是,通过个人资料/消息流程
Reddit是是是是,通过 wonda reddit chat start
X是是是是,通过 wonda x dm start
Reddit 聊天 / 私信

通过 WAB 发送私信。聊天使用已登录的 Reddit 浏览器会话,并可通过 --via wab 使用一等双生操作。无需单独的聊天令牌。

# Read
wonda reddit chat inbox                                  # List DM conversations with latest messages
wonda reddit chat messages <room-id> -n 50               # Fetch messages from a room

# Write
wonda reddit chat start <username> --text "Hey!"         # Start (or reuse) a DM with a user by username (no room-id needed)
wonda reddit chat send <room-id> --text "Hey!"           # Send a DM into an existing room (mimics browser typing behavior)

# Management
wonda reddit chat accept-all                             # Accept all pending chat requests

重要提示:每天发送私信的数量限制在 15–20 条,并使用多样化的文本,以避免被检测到。send 命令会驱动浏览器撰写框,并验证渲染后的消息。

云端数字孪生(wonda twin)

管理托管在云端、通过移动代理运行的社交 Persona。会话在服务器端运行;计划任务通过 cron 触发周期性任务(同步已保存内容、互动、运行 Agent)。

交互式(可观看)与无头模式:请先确认自己使用的是哪种界面。 云端孪生会以两种方式运行同一个反检测 Chromium,其中只有部分方式会实时串流屏幕,供你(或用户)观看并点击:

  • 可观看的交互界面(云端浏览器实时串流至 viewerUrl,你可以在本地 WAB 或任何浏览器中打开): wonda twin login、wonda twin view、wonda twin signup 和 wonda twin attach。当需要人类查看并操控云端浏览器时,请使用这些命令:登录、重新验证身份、创建全新账户,或处理任何需要人类操作的步骤。login/view/signup 会启动一次新的运行并取得该孪生的配置文件租约;attach 则不同——它会通过 <runId>(来自 wonda twin runs)连接到已经运行的任务,且绝不会取得租约,因此操作员可以按需观看(或接管)任何正在运行的任务——无论是自动驾驶任务、计划任务触发的任务,还是 run-now 命令启动的任务,而不仅是他们刚启动的会话。CAPTCHA(或任何升级验证挑战)只能在这些可观看界面上解决。你不能替用户输入凭据或解决验证码;请将 viewerUrl 交给用户,让他们完成操作,然后重新检查 wonda twin login-status / health / liveness。
  • 无头界面(没有屏幕、没有查看器、无人值守): wonda twin run-now、计划任务、wonda twin login-status、wonda twin seed-from-cookies,以及所有使用 --engine cloud 运行的平台操作。这些操作会在代理后方不可见地运行,没有人监看。如果遇到验证码或登录拦截,则无法在当前任务中解决,因此运行会直接失败(获取其 wonda twin artifact <runId> 截图以查看原因);或者,在任务仍在运行时,使用 wonda twin attach <runId> --control --open 接入并亲自操控,然后让任务继续运行。
  • 要接管正在运行的任务,请使用 wonda twin attach <runId> --control。 没有 wonda twin control 这个动词;要操控任意正在运行的任务,必须使用 attach --control(对于自己启动的查看任务,则使用 wonda twin view)。不带 --control 的 attach 是只读查看器。
  • 观看 / 截取串流查看器的屏幕截图(Agent):请使用 WAB,切勿使用裸 Playwright 或无头 Chromium 脚本。 login/view/signup 会在本地 WAB 内的一个标签页中打开查看器;该标签页就是观察界面,因此,wonda wab show <persona> 会显示窗口,而 wonda wab screenshot <persona> 则会截取 PNG,而不显示窗口。要通过只读 attach 截图,请省略 --control 和 --open,然后运行 wonda wab screenshot <viewerUrl> --output run.png --wait-until domcontentloaded --wait-for '#screen[width][height]'。只有在第一帧串流图像加载到画布后,attach 查看器才会为 #screen 添加 width 和 height 属性,因此这条命令会等待真实帧内容,而不只是等待查看器外壳或网络空闲。中继服务会将帧分发给多个只读查看器,因此可以在其他查看器同时运行时截取屏幕截图。只有控制权是单一归属的:如果有多个控制角色的查看器连接,第一个会保留控制权,后续查看器则会降为只读。请先确认任务确实在串流(wonda twin liveness <persona> → live:true),然后再构建任何观察器。 wonda twin login-automated 并不是无头登录的顺畅路径。这条流程不会自行完成登录;它始终会生成一个流式登录备用方案,并返回 { status: "needs_human", viewerUrl }。请将其视为“打开此 viewerUrl 并手动登录”,与 twin login 相同。

以下两点容易导致“它正在运行/它已登录”的误判:

  • --engine cloud 会保留一个温热的控制会话,并占用约 15 分钟的忙碌租约。 云端操作完成后,孪生体会在空闲时段内保持“忙碌”,因此后续的 twin login/view/signup(或另一个 --engine cloud 操作)可能会因忙碌而返回 409,直到租约到期。这是预期的温热会话行为,并非错误;请等待租约到期,或执行 wonda twin stop <persona>。
  • 查看器中的“You are now signed in”面板会持续显示。 它确认该会话中已检测到登录,并不表示当前仍有实时流打开。若要确认“此刻是否有实时交互流打开”,请使用 wonda twin liveness <persona>(标签页关闭约 30 秒后会变为 false);若要查看运行状态,请使用 wonda twin runs/wonda twin health。切勿根据持续显示的面板推断“仍在运行/仍在观看”。

MCP 孪生体接口将读取工具标记为 Always allow,将写入工具标记为 Needs approval。单次审批即可运行自动驾驶循环,请使用 run_campaign 和 schedule_loop;如需受监督的操作,请使用各平台对应的动词工具。

Claude 网页版和 Cowork 用户可以通过 https://wonda.sh/docs/connect-claude 将云端孪生体连接为自定义远程 MCP 连接器。

# Sessions
wonda twin list                                          # List twin sessions
wonda twin show <persona>                                # Show one session
wonda twin provision <persona> --region GB               # Provision (flags: --provenance, --spend-cap <microdollars>, --allow <cmd> (repeatable))
                                                         # --max-writes-per-hour <N>: max platform writes/hour before the soft cap logs+meters (0/unset = unlimited)
                                                         # --alert-webhook-url <url> + --alert-webhook-secret <secret>: HMAC-signed owner alert on needs_auth / consecutive failures (secret is write-only)
wonda twin update <persona> --spend-cap <microdollars>   # Change caps + alert webhook post-provision without re-provisioning (flags: --max-writes-per-hour <N>, --alert-webhook-url <url>, --alert-webhook-secret <secret>)
wonda twin pause <persona>                               # Pause a session
wonda twin resume <persona>                              # Resume a paused session
wonda twin needs-auth <persona>                          # Flag a session as needing re-auth
wonda twin needs-auth-view <persona> --platform x        # Flag needs_auth, then mint a REAL streamed LOGIN (not a read-only view) and open it in a DEDICATED tab inside your local WAB, the same one-shot re-auth flow the MCP tool performs. Signing in re-authenticates the twin and flips it back to active. Prints the viewer URL (served at <web-base>/twin-login.html, token in the URL fragment) so you can open it in any browser too. Login is human-gated (you cannot type credentials for them); one twin viewable at a time (open sequentially). (--platform <x|linkedin|reddit|instagram>, --web-base default https://wonda.sh)
wonda twin recover <persona>                             # Clear an ACTIVE critical safety signal (captcha / unusual-activity / account-restricted) AFTER you have resolved it in-browser. Those criticals do NOT change the twin status, so the safety gate hard-blocks the persona with NO auto-resume until you clear it; this appends a 'recovered' marker the gate reads to stop treating the critical as active. A security checkpoint / needs_auth is cleared by re-login (wonda twin login) instead, not this. -> { recovered, clearedSignalType, persona }
wonda twin login <persona> --platform instagram          # Open a born-in-cloud streamed login in a DEDICATED tab inside your local WAB (the cloud login looks like our antidetect browser, just on the cloud; an existing WAB session in your other tabs is left untouched). Spawns the persona's WAB visibly and opens the viewer at <web-base>/twin-login.html (token in the URL fragment); prints the viewer URL too so you can open it in any browser. On sign-in the stream stops and a Wonda "you are signed in" confirmation replaces it (the platform feed is hidden as you sign in). Unmetered. (--platform <x|linkedin|reddit|instagram>, --web-base default https://wonda.sh)
wonda twin signup <persona> --platform reddit            # Open a born-in-cloud account SIGNUP in a DEDICATED WAB tab and create the account by hand in the live stream (3-A fully-attended: you type the whole flow incl. any captcha/verification). A fresh persona is provisioned automatically; signup REFUSES to run over an already-active/needs-auth twin (use `twin login` to re-authenticate). It completes only when you press the Done action AND the cloud confirms the new account (session cookie set, no unresolved challenge); the created handle is then bound to the twin and the profile snapshots active. Unmetered. (--platform <x|linkedin|reddit|instagram>, --web-base default https://wonda.sh)
wonda twin signup <persona> --automated                  # Reddit only: the cloud AUTO-DRIVES the register form (mailbox, emailed code, username, password) up to the date-of-birth step, then PAUSES and shows a Resume banner in the stream. You type the DOB by hand (the automation struggles with Reddit's segmented birthday widget), then click Resume and the cloud finishes the remaining steps + saves. Add --dob YYYY-MM-DD to pre-fill the age step too (leaving only a challenge/onboarding for you). Needs redditAccountCreationEnabled + emailServerApiEnabled for the account. Platform is pinned to reddit.
wonda twin attach <run-id>                               # Attach a live VIEWER to an already-running twin run (run id from `wonda twin runs`). Unlike login/view/signup it does NOT start a run or take the profile lease: it registers read-only presence on the LIVE run and prints a browser-openable viewer URL so an operator can watch any live run (autopilot / schedule / run-now) on demand. Add --open to launch the viewer in your default browser. Add --control to attach as a drive-capable CONTROLLER (click/type into the live run) instead of a read-only watcher. 404 if the run is unknown/not yours; run_not_live if it is not live; run_not_attachable if it is a batch job that cannot stream. Unmetered; needs Premium (cloud twin).
wonda twin sync-cookies <persona> --run-id <run-id> --platform linkedin # Sync one platform's cookies from a LIVE cloud twin browser into that runner's cloud-only flat store. The platform must match the live view. Requests only session:sync-cookies and never prints or downloads cookie values. The refreshed store is available to the live runner immediately; writable views carry it into their next profile snapshot, while read-only views never persist runner changes and are rejected by the live service.
wonda twin seed-from-cookies <persona> --platform x      # Start a cloud seed job from browser cookies previously stored with /social-tokens. The run output carries per-platform login-status results.
wonda twin login-automated <persona> --platform x        # NOT a headless happy path: the route never completes a login on its own. It ALWAYS mints a streamed-login fallback and flags the twin needs_auth, returning { status: needs_human, viewerUrl } (viewUrl is the raw WebSocket for custom viewers). Open viewerUrl in a browser to finish the sign-in by hand (same as `twin login`), then re-check with login-status.
wonda twin login-status <persona> --platform x           # Read-only advisory signed-in check from a warm control session. While the control browser is still warming it returns { status: "warming", loggedIn: false, lastChecked: null, retryAfterMs } (HTTP 202, Retry-After header) and the CLI prints a stderr retry hint; a completed probe returns { status: "checked", loggedIn, lastChecked } (HTTP 200). Retry after the warming delay for a meaningful result.
wonda twin sync-profile <persona> --cookies-only         # Promote local WAB / local cookie jars to the cloud twin profile. Forces local WAB cookie sync first when that persona is running. Use --platform <x|linkedin|reddit|instagram> to limit scope, --dry-run to inspect, --include-storage to upload Chromium storage too.
wonda twin export-cookies <persona> --platform linkedin  # Import sanitized .seeded-cookies from the current cloud twin generation into local ~/.wonda/<platform>-cookies/<account>.json. Refuses newer local jars unless --force; --dry-run shows planned writes; --account-label overrides the local label; --inject-running explicitly pushes imported cookies into already-running bound WAB personas.

# Sharing (owner-only: a grantee can never re-share a twin granted to them)
wonda twin share add <persona> --email <email>           # Share a CLOUD twin with another Wonda account (they must already have one; unknown email -> 404 "ask them to sign up first"). Exactly one of --email or --org. --role operator (default) | read-only. Emails them by default; --no-notify grants silently. Needs Premium (cloud twin). Sharing with yourself -> 400; an existing live grant -> 409. If the notification fails the grant STILL succeeded: the response carries emailSent:false and the CLI warns on stderr, exit 0.
wonda twin share add <persona> --org <orgId> --role read-only   # Share with every member of an organization instead of one account. --no-notify is rejected here (an org share has nobody to email).
wonda twin share list <persona>                          # Who this twin is shared with: share id, grantee email (or org), role, createdAt. Owner-only (a grantee gets 403). NOT Premium-gated, so a lapsed owner can still audit access.
wonda twin share rm <share-id>                           # Revoke a share (id from `twin share list`). Owner-only; a share that is not yours -> 404 (never leaks that it exists). NOT Premium-gated, so a lapsed owner can always cut off access they granted.

# Using a twin someone shared WITH you: there is no separate surface. Address it by
# persona name through the normal twin/platform commands (`wonda twin show <persona>`,
# `wonda twin run-now <persona>`, `linkedin ... --account <persona>`); the server
# resolves a bare persona to your own twin first, else to a live grant.
#   - role operator drives the twin (login, view, run-now, actions); read-only reads metadata only.
#   - Owner-only routes stay denied even to an operator: `twin export-cookies` and rewriting the alert-webhook secret.
#   - A grantee can NEVER drive a home:local twin (it lives on the owner's machine), only home:cloud.
#   - If two different owners share the SAME persona name with you, the request is denied as ambiguous rather than guessed. Ask one of them to rename.
#   - Both sides need Premium: the twin routes check YOUR cloud-twin entitlement, and cloud dispatch also checks the OWNER's (their account pays for the run).

# Schedules
wonda twin schedule list --persona <persona>             # List schedules (--persona optional)
wonda twin schedule add <persona> --cron "0 9 * * *" --kind saved_sync --name saved-posts-scrape   # Add (--kind: saved_sync|engage|agent; --command, --prompt, --mode deterministic|agent)
                                                         # --name <label>: human-readable schedule label (e.g. saved-posts-scrape) for listings/audit; optional
                                                         # --command is tokenized quote-aware on the server, so a free-text write body (a post, comment, DM, or InMail) survives as one argument. Quote any body that has spaces.
                                                         # Posting/comment/DM schedules should use --kind engage so they count toward the write-velocity envelope.
                                                         # --jitter-window-seconds N: fire once/day at a random-looking minute within N seconds AFTER the cron time (the cron marks the window start); 0/omitted = fire exactly at the cron minute
                                                         # --jitter-min-seconds A --jitter-max-seconds B: fire at a deterministic offset in [A,B) seconds after the cron time. Either flag supersedes --jitter-window-seconds; the offset is stable per (schedule, day) so a retry keeps the same minute.
                                                         # --timezone <IANA>: read the cron in that zone (e.g. America/New_York) instead of UTC. On a fall-back day a repeated local time still fires ONCE; on a spring-forward day a local time that does not exist is skipped for that day.
                                                         # --at <RFC3339>: ONE-SHOT. Fires once at that instant then disables itself. Mutually exclusive with --cron (pass exactly one).
                                                         # --starts-at <RFC3339> / --ends-at <RFC3339>: activation window. Outside it the dispatcher skips the tick without consuming the slot, so the schedule lies dormant and resumes untouched.
                                                         # --output-webhook <url>: deliver each run's captured command stdout to your HTTPS webhook (payload carries a short-TTL signed download URL); --output-webhook-secret <s>: HMAC-SHA256 key signing the body via the X-Wonda-Signature header
wonda twin schedule add <persona> --kind engage --cron "0 10,14,17 * * 1-5" --jitter-window-seconds 1200 --commands "linkedin feed-engage --authors 'alice,bob' --duration 5m"   # Recurring feed-engage on the cloud twin
wonda twin schedule add <persona> --kind engage --cron "0 9 * * 1-5" --timezone America/New_York --jitter-min-seconds 300 --jitter-max-seconds 1800 --command "linkedin post 'morning thought' --via wab --account <persona>"   # Weekday 9am NEW YORK time, 5-30min of jitter
wonda twin schedule add <persona> --kind engage --at 2026-08-01T09:00:00Z --command "x tweet 'launch day' --via wab --account <persona>"   # One-shot: fires once, then auto-disables
wonda twin schedule add <persona> --kind engage --cron "0 9 * * 1-5" --command "x tweet 'gm builders' --via wab --account <persona>"   # Scheduled posting with free-text argv preserved
                                                         # NOTE: pass targets inline with --authors (comma-separated, no spaces). --authors-file is local-only; the cloud runner has no filesystem for the file.
                                                         # Platform verbs in schedules are validated against the twin action registry; unknown LinkedIn/Reddit/X/Instagram verbs are rejected even when the twin allowlist is empty.
wonda twin schedule enable <id>                          # Enable a schedule
wonda twin schedule disable <id>                         # Disable a schedule
wonda twin schedule rm <id>                              # Delete a schedule

# Runs
wonda twin runs --persona <persona> --limit 20           # Recent runs. Each run carries hasArtifact:true when a FAILED run captured a diagnostic screenshot/bundle (fetch with `wonda twin artifact`).
wonda twin run-now <persona> --command <cmd>             # Trigger a run immediately and capture its structured command output. A WRITE command over the per-identity action limit returns a structured throttled 429. --command is tokenized quote-aware, so quote a free-text body that has spaces: --command "linkedin send-message alice 'hi there :)' --via wab --account alice"
                                                         # Platform verbs are validated against the twin action registry; non-platform commands still pass through the normal allowlist behavior.
                                                         # Media write verbs accept Wonda media ids or signed URLs on the twin: reddit submit --media <media-id>, x tweet/reply/quote --attach <media-id>, linkedin post --media <media-id>. The runner fetches bytes to /tmp and passes a local file path to the platform CLI.
wonda twin run-action --persona <p> <platform> <action> --field key=value   # [DEPRECATED: prefer `<platform> <verb> --engine cloud`] Run one registry-validated action through the warm hosted control session. Still works so running agents are not broken. If cold, returns { status: "warming", retryAfterMs }. Use --payload @file.json for structured payloads. Requires the Premium plan (cloud twin).
wonda twin output <runId>                                # Fetch a run's captured command output by either the twinRunId returned from run-now or the runtime runId shown by twin runs (--url prints just the short-TTL signed download URL; new captures are retained privately for 30 days)
wonda twin artifact <runId>                              # Print signed download URLs for a FAILED run's diagnostic screenshot (image/png, opens inline) + failure-bundle tar.zst, each on its own line. 404 if the run captured neither. Requires the Premium plan (cloud twin).

# SENSE layer (read-only "ask before you act" probes; reuse the EXACT decision + caps the write gate enforces)
wonda twin can-act --persona <p> [--action connect]      # Would this twin run this verb (or any write, no --action) right now? -> { canAct, reason, code, deferUntil, actionsRemaining }. Reads/generation always pass.
wonda twin actions --persona <p>                          # Per-action remaining limit + consumed-today + rolling-7d, plus the resolved cap `mode` (global aggregate floor + connect/message/like/comment/visit). `limit` is null when uncapped (unlimited mode).
wonda twin health --persona <p>                           # Liveness (active|paused|needs_auth) + signalCooldown (the derived graded cooldown: strongest unresolved platform signal) + recentSignals (the append-only health-record tail: 429s, captchas, checkpoints). When an unresolved critical (captcha / unusual-activity / account-restricted) is active it prints a `run: wonda twin recover <persona> after resolving in-browser` hint to stderr (stdout JSON is untouched).

# Action caps (per-twin MODE + custom overrides the safety gate enforces)
wonda twin limits get <persona>                           # Show the twin's cap mode (warmup|conservative_steady|moderate_max|unlimited) + custom overrides
wonda twin limits set <persona> --mode moderate_max       # Set the cap mode. unlimited = NO caps at all (no global, no per-action, no weekly)
wonda twin limits set <persona> --connect 30 --message 60 # Set CUSTOM daily caps per action (UNCLAMPED, own risk): --connect/--message/--like/--comment/--visit, --global <N> (daily aggregate), --*-weekly <N> (rolling-7d). Passing override flags MERGES into the stored overrides (other custom caps are kept); --clear-overrides drops them all back to the mode.
本地 WAB 中继(wonda relay)

在本机的本地 WAB 上运行已注册的孪生体操作,同时让调用方继续使用云端代理和相同的 /twin/sessions/{persona}/actions/{platform}/{action} API。

relay health 和 relay restart 要求 Wonda CLI v1.57.0 或更高版本。调用任一命令前,请先检查 wonda --version。如果版本较旧或未知,请勿尝试执行不可用的命令:使用 wonda doctor --relay 代替 relay health。请勿用 relay install 代替 relay restart,因为如果重新安装时未包含每个已配置的 --persona,就可能替换中继的 persona 集合。请说明安全重启 CLI 需要 v1.57.0+,并在该版本发布后提醒用户升级。

wonda relay pair                                        # Pair this machine with your Wonda account using the existing browser login flow
wonda relay run --persona <p>                           # Long-poll the cloud broker and serve actions for a persona
wonda relay status --persona <p>                        # Show local relay configuration
wonda relay health                                      # v1.57.0+. One-line verdict for this machine's relay: state (connected|standby|degraded|offline) + reason (ok, standby, not-installed, not-running, waiting-for-sign-in, hook-unreachable, unpaired, bootstrapping, browser-bootstrap-failed, broker-disconnected, broker-unreachable, broker-unknown, self-update-failed, version-mismatch, version-blocked). `standby` means the relay is healthy here but another of the account's devices is the active one, so this machine serves nothing until the user picks Make active on the setup page: working as designed, not a fault. `waiting-for-sign-in` is a Windows box with the task registered and nobody signed in: expected, not a fault, so do not report it as a failure. `hook-unreachable` is a live relay process whose loopback status hook cannot be read (custom --local-hook-port, or the standard ports taken): the relay may well be serving, only unobservable locally. The JSON also carries `serving` (true|false|absent) mirroring the relay's own poll answer; absent means unknown (old relay or backend, or the last poll failed), never standby. `version-blocked` means the server's version policy refuses NEW actions from this relay until it updates (it can still report serving=true, so blocked outranks green) + summary/detail/hint, plus running/paired/supervised, version, personas, connected/disconnected, logPath. Branch on `reason`, never on the message. The macOS menu-bar dot's FORENSIC tier: the dot's steady-state poll reads the relay's loopback /status over HTTP directly (no CLI spawn) and only fast-classifies a healthy current-binary serving/standby payload; this command runs on HTTP silence, on state transitions, after user actions, AND keeps recurring at the 15s throttle for as long as the payload cannot be fast-classified (a sustained fault such as unpaired / bootstrapping / blocked / version drift, or an old relay that does not report `serving`), because the forensic verdict is then the dot's only source of state. Recurring `relay health` subprocesses during a persistent fault are therefore expected, not a bug; only the healthy steady states are spawn-free. `wonda doctor --relay` prints the same facts check by check
wonda relay restart                                     # v1.57.0+. Restart the installed relay. macOS: `launchctl kickstart -k` when launchd already supervises this binary, else falls back to the full `relay install` path (rewrites the plist, bootstraps it). Windows: re-registers and restarts the Scheduled Task. Preserves the personas the autostart already serves unless you pass --persona
wonda relay stop --persona <p>                          # Clear cloud relay presence for a persona (this does NOT stop the local relay process; use `wonda relay disable` to stop it, `wonda relay restart` to bounce it, or `wonda relay uninstall` to remove the autostart)
wonda relay disable                                     # Stop the running relay AND turn its autostart off persistently, so nothing brings it back until `relay enable`/`app open`. macOS: launchctl bootout + a persistent launchctl disable (survives KeepAlive and the next login). Windows: schtasks /End + stop the relay processes /End leaves behind + /Change /DISABLE (survives logon triggers and restart-on-failure). Both also stop a relay started by hand with `relay run` in any supported spelling (the `relay start` alias, inherited flags in either legal position; this user's only) and verify the outcome: the command fails instead of reporting a stop that did not happen. Keeps the plist/task, so the personas survive for re-enable. This is the process-level stop; `relay stop` is the unrelated broker-presence clear
wonda relay enable                                      # Inverse of disable. macOS: clears the launchd disable override FIRST (a disabled service refuses to bootstrap), then takes the cheapest path that ends with a running relay: an already-supervised relay with a live pid is left alone, a correctly loaded job with no live pid (KeepAlive backoff, manual `launchctl stop`) gets a plain kickstart (mode "kickstart", no plist rewrite), and every other state reruns the full install path (rewrite plist + bootstrap; mode "reinstall"). Windows: schtasks /Change /ENABLE, then a live-relay pid check before /Run: a relay that is already running, whether the task's own instance or one started by hand with `relay run` (which the task's IgnoreNew policy cannot see), is left alone, and only a machine with no live relay gets /Run; an unregistered task is installed fresh. Preserves the installed personas, like `relay restart`
wonda relay install [--persona <p>]                     # Install the relay to auto-start at login and stay running. macOS: LaunchAgent (restarts on crash, logs to ~/Library/Logs/wonda-relay.log). Windows: per-user Scheduled Task launched through a hidden VBScript wrapper (logon trigger + restart-on-failure, no admin, no password, no console window). Re-run to point autostart at a new binary. A Homebrew Cellar path is auto-rewritten to the stable opt symlink so brew cleanup can't delete the target. The .pkg and Windows installer run this for the installing console user; CLI-only channels (brew formula, npm, install.sh) get it via `wonda app install` (install.sh offers that interactively; brew/npm only PRINT the pointer, because package hooks cannot run setup: pnpm 10/Bun block lifecycle scripts and npm v12 disables them by default). A one-time nudge also points interactive CLI use at `wonda app install` on machines with neither the app nor the relay autostart (TTY-only, never in CI, once per machine via a ~/.wonda marker). Package managers have no uninstall hooks, so the clean removal order is `wonda app quit` FIRST, then brew/npm uninstall; an orphaned at-login mechanism left by skipping that is inert (silent no-op at login, no error spam). Headless/MDM pkg installs and additional Mac users run `wonda relay install` or `wonda app open` once themselves
wonda relay uninstall                                   # Remove the relay autostart. macOS: stop the LaunchAgent and delete its plist. Windows: delete the Scheduled Task and its VBScript wrapper
wonda app install [--release <tag>]                     # The bridge from a CLI-only install (brew formula, npm, curl) to the full desktop experience: downloads THIS CLI version's signed installer from the releases (macOS: notarized wonda-macos.pkg; Windows: wonda-windows-setup.exe), verifies its SHA-256 against the release's checksums.txt (a missing entry is a hard failure, never an unverified run), and runs it. macOS: `sudo installer -pkg ... -target /` with the normal sudo prompt, then continues into `app open`; Windows: launches the setup program DETACHED and exits (the installer kills running wonda.exe processes to free the image, this one included, and finishes the whole setup itself). Idempotent: the exact version already installed (macOS: pkgutil receipt for sh.wonda.cli; Windows: the Add/Remove Programs record) offers a reinstall, default no. Without a TTY it prints the download URL and manual steps instead of running anything. Dev builds skip with a message; the hidden --release <tag> installs a specific release (the live-test seam). Exempt from the minimum-version gate: a version-blocked CLI must be able to fetch the current installer, which is the remedy for its own condition. First-run nudge: an interactive CLI on a machine with neither the app nor the relay autostart prints one pointer at this command, once ever (marker in ~/.wonda), never in CI or scripts
wonda app open                                          # Desktop-app open, what /Applications/Wonda.app (macOS; a tiny shim that runs ONE fixed path: the pkg's root-owned payload CLI under /Library/Application Support/Wonda; no per-user or PATH fallback, so no cross-user swap surface, while the relay itself is still handed to your verified self-updating ~/.wonda binary by the Go side) and the Start Menu "Wonda" entry (Windows; a hidden VBS launcher the installer writes) run: heal + enable the relay autostart (healthy relay not bounced), register Wonda to come back at login, and show the tray icon. macOS login mechanism: an Open at Login entry (System Settings > General > Login Items) pointing at /Applications/Wonda.app; with that app not installed (a CLI-only machine), a terminal run OFFERS to fetch it via the `app install` flow (y/N, default no; never a silent download), and otherwise the entry is skipped and reported (`loginItem: skipped-app-not-installed`, plus an `appInstallHint`). Windows: writes a hidden Startup-folder launcher (wonda-startup.vbs, per-user, runs `wonda app open` at sign-in, silent no-op if wonda.exe is gone) rewritten on every open, so a later NSIS install repoints the same file (never duplicates); the relay's Scheduled Task keeps its own logon trigger independently. Idempotent, and serialized: concurrent opens cannot stack tray icons or login items. PARTIAL-SUCCESS EXIT CONTRACT: `app open` exits 0 even when a sub-step fails (it launches from Finder or the Start Menu with no terminal; the tray badge is the failure surface), reporting failures in the JSON result as `relayError`, `loginItemError`, `appInstallError`, `startupEntryError`, or `trayError`. Automation must inspect those fields, never the exit code alone
wonda app quit                                          # Desktop-app quit, what the tray's "Quit Wonda" runs: `relay disable` (verified, incl. a hand-run `relay run`) + remove every come-back-at-login mechanism + remove the icon. macOS: deletes the Open at Login entry for the Wonda app, verified by enumeration (the script deletes every entry for the path and returns how many remain): an entry that survives removal fails quit non-zero with the fix, icon left up to say why, and cannot wedge (deleting the entry in System Settings makes the next quit succeed). With NO app bundle on disk the System Events call is skipped entirely (`loginItem: skipped-app-not-installed`), sparing CLI-only machines the Automation prompt (an entry pointing at a missing app is inert at login). Windows: deletes the Startup-folder launcher, and a launcher that cannot be removed (beyond already-absent) fails quit non-zero with the fix, because it would reopen Wonda at the next sign-in. One documented blind spot: with the macOS Automation permission denied, entries can be neither removed nor counted, so quit completes, reports `loginItemError` plus a note, and any Open at Login entry that exists WILL reopen Wonda at the next login until removed by hand in System Settings > General > Login Items. Personas and sign-in are kept. Clean uninstall order: `wonda app quit`, THEN brew/npm uninstall (they have no uninstall hooks of their own; the NSIS uninstaller does its own cleanup)

中继在你的真实设备和 IP 上运行。平台 Cookie 保留在本地。只有在设备和 wonda relay run 均运行时,它才会提供操作。如果没有正在运行的中继,代理会将相同的孪生体操作调用路由到云端孪生体。

运行孪生体上的任何操作时,安全保护都是内在机制。 账户安全并非序列器的特殊功能,而是“在孪生体上运行命令”的固有属性。相同的单身份安全防护机制会通过同一条执行路径,使用同一个共享的单身份计数器,保护临时 Agent(wonda linkedin connect --account <name>)、自动驾驶、twin schedule 和用户编写的序列。因此,某个 persona 在某一天执行了大量临时操作,会自动压缩该 persona 的剩余额度(每个身份只有一套上限,不会重复计数)。上限是每个孪生体的模式(warmup / conservative_steady(默认)/ moderate_max / unlimited;通过 wonda twin limits set 设置),用于选择每项操作的每日上限、每项操作滚动 7 天的每周上限,以及全局每日总量上限;unlimited 会关闭所有上限,自定义覆盖值则不受限制。安全防护会根据命令的 argv 对其进行分类:写入/社交操作命令(connect、send-message、like、comment、visit 等)会受到限制;读取操作(connection-status、conversations、profile、search)、生成操作(image/video/text)和未知命令则可不受限制地通过。这就是为什么会提供 SENSE 动词:Agent 会在执行前询问 can-act/actions/health,然后根据类型化结果选择分支,而不是先尝试写入操作再捕获拒绝结果。

通用序列(MCP 和公共 API)

序列是一种持久化的 Wonda 工作流,而非外联活动。它恰好包含四种可组合的步骤类型:

  • run:一个真实的 Wonda argv。生成的 CLI 清单会校验命令路径、嵌套的 Sales Navigator/X DM/Reddit 聊天动词、长标志和位置参数数量。
  • wait:精确或范围间隔,例如 2h ± 15m 或 3m-9m,并以确定性方式采样。
  • if:对 {{vars.*}}、较早的 {{steps.<id>.*}} 结果和当前项绑定执行普通条件判断。AND 的优先级与 OR 的常规优先级相同。
  • each:对任意数组进行有界的顺序扇出,使用 {{item}} 和可选别名。默认 500 项,显式上限为 5,000 项。

使用 MCP 工具 sequence_validate、sequence_create、sequence_run、sequence_runs、sequence_update、sequence_cancel_run 和 sequence_schedule。创建前先验证。创建手动或计划运行前,会检查每个必需的 {{vars.*}} 值。计划运行是可选的,接受经过验证的 5 字段 cron 表达式和 IANA 时区,或一次性执行时间、确定性抖动、已存储的变量以及显式设置的 allowOverlap(默认为 false)。

Relay 执行由清单驱动,不受注册表限制:每个生成的 LinkedIn、Sales Navigator、X 和 Reddit 命令都可以在配对的机器上运行,包括仅限本地的命令,例如 X DM。transport: auto 会在 Premium 云端首选项遇到定义要求使用上述仅限本地命令之一时,回退到 relay。每次运行都会记录其定义、解析后的传输方式、组织计费范围和触发方式的快照,因此编辑或上下文变更不会改写已在执行中的工作。

统一错误分类(根据 code 分支判断,切勿依据消息)。 每个 twin/outreach 接口都会返回现有的 { error: { code, message } } 信封;配额拒绝时还会附带 deferUntil(配额重置的 ISO 时间)和 reason(细粒度的门控信号)。Agent 根据类型化的 code 进行分支判断:

code含义Agent 应执行的操作
throttledWRITE 被按身份设置的安全门拦截(统称为 HTTP 429)。具体原因见 reason(limit_hit / weekly_limit_hit / warmup_frozen)。等到 deferUntil 后重试,或选择其他发送方。
limit_reached按操作设置的每日上限(connect / message / like / comment / visit,依据 twin 的上限模式)已在 UTC 当日用尽。等到 deferUntil(下一个 UTC 午夜),或使用其他操作 / 发送方。
limit_exhausted全局每日汇总上限(_all 下限)或按操作设置的滚动 7 天每周上限已用尽。在 deferUntil 前暂停使用此身份;切换到另一个 twin,或通过 wonda twin limits set 调高上限模式。
needs_authtwin 的会话需要重新认证(Cookie 过期 / 检查点)。运行 wonda twin login <persona>;不要重试该写入操作。
sender_blocked此身份因健康状况而停止:twin 已暂停 / 预热已冻结、存在尚未解决的严重平台信号(验证码 / 异常活动 / 账号受限,或持续的 429 风暴),或中继已离线。这是健康状况导致的停止,而非普通上限。停止使用此身份;检查 wonda twin health。若存在活跃的严重问题,在浏览器中解决后运行 wonda twin recover <persona>。
command_not_allowed命令不在 twin 的权限允许列表中,或指定了未注册的 LinkedIn / Reddit / X / Instagram 动词。对于允许列表拒绝,通过 --allow <cmd> 重新配置;删除未注册的平台动词。
unsupported_channelargv 指向 twin 或 CLI 无法运行的平台 / 动词。此 twin 不支持该 wonda 命令;请删除。
invalid_payload实时流操作负载格式错误,包括无效的媒体引用(既不是 Wonda 媒体 ID,也不是 https:// URL)。修正负载后再重试。
media_not_foundtwin 媒体操作中的 Wonda 媒体 ID 不属于调用者,或没有存储对象。使用运行 twin 的账号所拥有的媒体 ID。
media_fetch_failed运行器无法将已解析的媒体 URL 下载到该操作的临时目录中。使用新的签名 URL 或可访问的 Wonda 媒体 ID 重试。
not_foundtwin / campaign / 资源不存在。请先配置 / 创建。
deferred结构化的非错误延后:在 BATCH 中,安全门丢弃了一条超出上限的命令,并运行其余命令。在 deferUntil 后重新入队该延后的命令。
wonda twin can-act 对于拒绝操作返回的 code + reason 与之后实际写入时返回的内容相同,因此 Agent 从 can-act 读到 code: "needs_auth",然后在写入时看到 needs_auth,就可以根据同一个代码进行分支判断。
日历(wonda calendar)

这是一个只读信息源,整合了两类原本需要分别检查的内容:即将触发的双生体计划,以及过往运行和平台操作。时间会按真实时区解析,因此“星期二”指的是用户所在时区的星期二。

wonda calendar                                              # This civil month, in the detected machine IANA timezone (UTC fallback)
wonda calendar --from 2026-07-01 --to 2026-07-31 --timezone Europe/Paris
wonda calendar --all                                        # Include days with nothing on them
wonda calendar day 2026-07-24 --timezone Europe/Paris --limit 200

时间范围查询只返回每天的计数;calendar day 则返回各条具体记录。这样的划分是有意为之:繁忙的账户一个月内会有数万条记录,而月历网格只会显示计数。

以下两个维度绝不能相加:counts.run 是双生体运行次数,actions 是来源无关操作日志中的记录数。一次运行会执行许多平台操作;而通过中继在用户自己的机器上运行的操作,不会产生任何云端运行。系统会明确说明数据可能不完整,而非让人自行推断:truncated.scheduleFires 表示计划触发记录的枚举已达到上限,因此这些计数是下限。

工作流与发现

品牌提取(brand extract)

提取网站的设计系统(颜色、字体排印、圆角半径、阴影、间距、字体、Logo、主视觉装饰、CSS 图案背景、虚线/点线边框样式、:root 自定义属性、标题强调样式、胶片颗粒/噪点叠加层),并生成 DESIGN.md、tokens.json 和 assets/。通过捆绑的隐身浏览器和 Chromium 驱动在本地运行(与 wonda wab record 及经过身份验证的会话流程使用相同的 wonda wab install)。

需要先运行一次 wonda wab install,以下载隐身浏览器和 Chromium(约 300 MB;wonda wab record、经过身份验证的会话流程和 brand extract 共用)。

这是内置替代方案,取代了之前在 slide-generation / creative-static-ads / premium-static-ads 技能中使用的基于 npx 的品牌提取 CLI。

# Local-only — no auth, no credits, no API call
wonda brand extract https://linear.app                       # Writes ./output/linear.app/{DESIGN.md, tokens.json, assets/}
wonda brand extract https://stripe.com --output ./refs       # Writes ./refs/stripe.com/...
wonda brand extract https://vercel.com --screenshot          # Also writes page.png
wonda brand extract https://stripe.com --viewport 1440x900   # Override default 1920x1080

# Persist to the server (uploads assets via media presign + POSTs /brand/save)
wonda brand extract https://stripe.com --save                # Local + persist
wonda brand extract https://stripe.com --save --make-active  # Local + persist + activate (the common path)
wonda brand extract https://stripe.com --no-output --save    # Don't write to disk, persist only

# Move a persisted brand around
wonda brand save --from ./output/stripe.com --make-active    # Persist a previously-extracted dir
wonda brand pull <brand-id>                                  # Download a saved brand back to ./output/<domain>/

标志:

  • --save:通过媒体预签名流程上传 assets/,并向 /api/v1/brand/save 发送 POST 请求,提交 {tokens, mediaIds}。需要身份验证。
  • --make-active:隐含 --save。将新品牌设为当前活动品牌。
  • --output <dir>:覆盖本地输出目录。默认为 ./output/<domain>/。不能与 --no-output 同时使用。
  • --no-output:不写入磁盘(用于管道传递的内存提取)。不能与 --output 同时使用。
  • --name "Brand Name":覆盖保存时使用的品牌名称。默认为首字母大写的域名主体。
  • --screenshot:同时在 DESIGN.md 旁保存 page.png。
  • --viewport WxH:无头浏览器的视口大小。默认为 1920x1080。

输出(未设置 --no-output 时,始终写入 <output-dir>/<domain>/):

  • DESIGN.md:令牌、字体排印、主视觉装饰、Logo、CSS 图案、虚线边框和根级 CSS 变量的 Markdown 摘要。在编写 HTML 前,请先在幻灯片/静态广告技能中阅读此文件。
  • tokens.json:提取结果的原始结构化 JSON。
  • page.png:仅在传入 --screenshot 时生成。
  • assets/:原始主视觉装饰文件;对于任何非 Google @font-face URL,还会生成 assets/fonts/。未设置 --no-output 时始终写入。

会将写入的文件路径打印到标准输出。使用 --save 时,还会打印 API 响应(brandId、sourceDomain、warnings)。失败时以非零状态退出(网络错误、导航超时、浏览器崩溃、保存失败)。

视频分析

分析视频,提取复合画面网格(视觉)和音频转录文本。可用于在制作不同版本前了解视频内容。需要完整账户(非匿名),并根据视频时长扣除额度(按 ElevenLabs STT 定价)。

如果视频刚上传完成且仍在标准化处理中,CLI 会自动重试,直到媒体就绪。

# Analyze a video — returns composite grid image + transcript
ANALYSIS_JOB=$(wonda analyze video --media $VIDEO_MEDIA --wait --quiet)

# The job output contains:
# - compositeGrid: image showing 24 evenly-spaced frames
# - transcript: full text of any speech
# - wordTimestamps: word-level timing [{word, start, end}]
# - videoMetadata: {width, height, durationMs, fps, aspectRatio}

# Download the composite grid for visual inspection
wonda analyze video --media $VIDEO_MEDIA --wait -o /tmp/grid.jpg

# Get just the transcript
wonda analyze video --media $VIDEO_MEDIA --wait --jq '.outputs[] | select(.outputKey=="transcript") | .outputValue'

错误处理:402 = 额度不足,409 = 媒体仍在处理中(CLI 会自动重试)。

电子邮件

管理一次性电子邮件帐户并阅读邮箱邮件。这些命令需要启用 emailServerApiEnabled 标志。

wonda email account create [email]                    # Create an email account
wonda email account create --random --domain <domain> # Create an email with a random username
wonda email account create --username <name> --domain <domain> # Create an email with a chosen username
wonda email account get <email>                       # Get email account details
wonda email account delete <email>                    # Delete an email account

wonda email inbox list <email>                        # List inbox messages
wonda email inbox read <email> <id>                   # Read a specific email with verification codes
wonda email inbox wait <email> --timeout 60           # Wait for a new email to arrive
wonda email inbox wait <email> --since "$SINCE"       # Only messages after an RFC 3339 timestamp
wonda email inbox wait <email> --since-id "$MAX_ID"   # Only messages with id greater than this

对于注册流程,请在触发验证邮件前捕获 --since,或使用 wonda email inbox list <email> --jq '[.[].id] | max // 0' 快照当前最大邮件 ID,并将其传递给 --since-id。

任务
wonda jobs get inference <id>                         # Inference job status
wonda jobs get editor <id>                            # Editor job status
wonda jobs get publish <id>                           # Publish job status
wonda jobs wait inference <id> --timeout 20m          # Wait for completion
发现
wonda models list                                     # All available models
wonda models info <slug>                              # Model details and params
wonda operations list                                 # All editor operations
wonda operations info <operation>                     # Operation details
wonda capabilities                                    # Full platform capabilities
wonda pricing list                                    # Pricing for all models
wonda pricing estimate --model seedance-2 --prompt "..." # Cost estimate
wonda style list                                      # Available visual styles
wonda balance                                         # Current credit balance (org wallet in org context)
wonda usage                                           # Spend summary for the current month (per model/project)
wonda usage --month 2026-05                           # ...for a calendar month
wonda usage --from 2026-04-01 --to 2026-06-30         # ...for a custom range
wonda usage --project acme-launch                     # ...restricted to one project
wonda project list                                    # Spend-tagging projects in the active scope
wonda project create acme-launch                      # Create one (org scope: admin/owner only)
wonda use --project acme-launch                       # Tag subsequent spend with it (sticky)
wonda topup                                            # Top up credits (opens Stripe checkout)
编辑音频和图像
# Edit audio
wonda edit audio --operation <op> --media <id> --wait -o out.mp3

对于任何图像编辑(裁剪、文字叠加、img2img、移除背景、矢量化),请获取专用技能:wonda skill get image-edit。

对齐(时间戳提取)
wonda alignment extract-timestamps --model <model> --attach <mediaId> --wait

质量级别

级别图像模型分辨率视频模型适用场景
标准gpt-image-2(自动)——备选:nano-banana-2 1K1024×1024 / 1024×1536(gpt)/ 1K(nano)seedance-2(高,5s)默认选项。gpt-image-2 最擅长遵循提示词并生成图像内文字;nano-banana-2 适合更快地进行 Gemini 迭代,并支持多参考图。
高gpt-image-2(高)——备选:nano-banana-2 2K1024×1024 / 1024×1536(gpt)/ 2K(nano)seedance-2(高,15s)输出清晰。对 gpt-image-2 使用 --params '{"quality":"high"}',或对 nano-banana-2 使用 --params '{"resolution":"2K"}' 提升分辨率。也可选择 sora2pro。
最高nano-banana-pro 4K——备选:nano-banana-2 4K4Kseedance-2(高,15s)真正的 4K(gpt-image-2 上限为 1536px)。使用 --params '{"resolution":"4K"}'。视频也可选择 sora2pro(1080p)。

故障排除

现象可能原因解决方法
Sora 拒绝图像图像中有人物切换到 kling_3_pro
视频中出现源图像里没有的物体动作提示词描述了图像中不存在的元素简化为仅描述镜头移动和氛围
视频中的文字无法辨认AI 尝试在生成过程中渲染文字从视频提示词中移除文字,改用 textOverlay
手部看起来不自然提示词中包含复杂的手部动作简化为被动姿势,或调整取景以排除手部
系列作品风格不一致没有共同的参考图使用 --attach 指定相同的参考图
对步骤 A 的更改未反映在步骤 B 中渲染结果过期重新运行所有下游步骤

时间预期

  • 图像:30s - 2min
  • 视频(Sora):2 - 5min
  • 视频(Sora Pro):5 - 10min
  • 视频(Veo 3.1):1 - 3min
  • 视频(Kling):3 - 8min
  • 视频(Grok):2 - 5min
  • 音乐(Suno):1 - 3min
  • TTS:10 - 30s
  • 编辑器操作:30s - 2min
  • 口型同步:1 - 3min
  • 视频升频:2 - 5min

错误恢复

  • 未知模型:wonda models list
  • 没有 API 密钥:wonda auth login 或设置 WONDA_API_KEY 环境变量
  • 任务失败:使用 wonda jobs get inference <id> 查看错误详情
  • 参数错误:使用 wonda models info <slug> 查看有效参数
  • 超时:wonda jobs wait inference <id> --timeout 20m
  • 积分不足(402):使用 wonda topup 充值 LinkedIn WAB 附件:使用 linkedin send-message <target> [text] --attach <local-path> 附加一个受支持的本地文件(bmp/gif/jpeg/jpg/png/doc/docx/pdf/mp4/m4a,最大 20,000,000 字节)。添加 --dry-run 可暂存上传而不发送。云模式不接受本地路径。

评论

支持 Markdown