Skip to content

feat: add macOS send command#21

Open
BiboyQG wants to merge 2 commits intojackwener:mainfrom
BiboyQG:codex/macos-send-command
Open

feat: add macOS send command#21
BiboyQG wants to merge 2 commits intojackwener:mainfrom
BiboyQG:codex/macos-send-command

Conversation

@BiboyQG
Copy link
Copy Markdown

@BiboyQG BiboyQG commented Apr 24, 2026

Summary

Adds a wx send <CHAT> <MESSAGE> subcommand for macOS. The command activates WeChat, uses the WeChat search shortcut to open the requested chat, pastes the message into the focused input, and presses Return to send it.

Motivation

Recent macOS / WeChat builds can expose only the title-bar controls through Accessibility, which makes element-based automation unreliable. This implementation avoids AX child selectors and uses the keyboard-driven search flow that was verified against the current WeChat desktop UI.

User Impact

  • Users can send a text message from the CLI with wx send "张三" "你好" on macOS.
  • The command validates empty chat names and empty messages.
  • Non-macOS platforms return a clear unsupported-platform error.
  • The command requires WeChat to be logged in and requires Accessibility permission for the invoking terminal or agent app.
  • The implementation uses the text clipboard for paste reliability and restores the previous text clipboard value afterward when possible.

Docs and Skill

  • README now lists send in the feature summary, includes a wx send example, and documents the macOS/Accessibility/clipboard behavior.
  • SKILL.md now teaches agents when and how to use wx send, including the requirement to get explicit user confirmation before sending a real WeChat message.

Verification

  • cargo check passed.
  • rustfmt --check src/cli/send.rs passed.
  • Embedded AppleScript compiled with osacompile.
  • wx send --help passed.
  • cargo build --release passed.
  • Live macOS WeChat test sent wx-cli test 2026-04-24 to chat 邦邦; Computer Use verified the chat opened and the message was visible.
  • Local setup was completed on this Mac: WeChat was ad-hoc signed, wx init completed, wx sessions, wx history "邦邦" -n 3, and wx search "wx-cli test" --in "邦邦" -n 5 all worked.
  • The updated skill was installed locally into ~/.codex/skills/wx-cli/SKILL.md for future Codex sessions.

Notes

Cross-target checks were attempted but this Mac is missing the required cross C toolchains for bundled native dependencies:

  • cargo check --target x86_64-unknown-linux-gnu fails before this crate on missing x86_64-linux-gnu-gcc for libsqlite3-sys / zstd-sys.
  • cargo check --target x86_64-pc-windows-msvc fails before this crate on missing Windows C headers/toolchain for libsqlite3-sys / zstd-sys.

@BiboyQG BiboyQG changed the title [codex] add macOS send command feat: add macOS send command Apr 24, 2026
@BiboyQG BiboyQG marked this pull request as ready for review April 24, 2026 14:53
Copilot AI review requested due to automatic review settings April 24, 2026 14:53
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new wx send <CHAT> <MESSAGE> CLI subcommand intended for macOS that automates sending a WeChat message via osascript + keyboard-driven UI flow, and documents the new feature in the README.

Changes:

  • Introduce src/cli/send.rs implementing cmd_send (macOS AppleScript automation + non-macOS unsupported error).
  • Wire Send into the clap subcommand enum and dispatch in src/cli/mod.rs.
  • Update README.md feature list and add usage/documentation for wx send.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/cli/send.rs New send implementation using osascript, clipboard paste, and Return-to-send; includes platform gating.
src/cli/mod.rs Registers Send subcommand and dispatches to send::cmd_send.
README.md Documents the new send feature and provides a usage example + macOS permission notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/cli/send.rs
Comment on lines +59 to +70
if chat.trim().is_empty() {
bail!("聊天对象名称不能为空");
}
if message.is_empty() {
bail!("消息不能为空");
}

let output = Command::new("osascript")
.arg("-e")
.arg(SEND_SCRIPT)
.arg(&chat)
.arg(&message)
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

message 只用 is_empty() 校验会放过仅包含空格/换行的内容,与 PR 描述里“验证空消息”不一致。建议改为基于 message.trim() 判断空白,并(可选)像 chat 一样将 chat.trim() 的结果用于传给脚本/打印,避免用户输入前后空格导致搜索不到会话。

Copilot uses AI. Check for mistakes.
Comment thread src/cli/send.rs
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
let reason = if stderr.is_empty() {
format!("osascript exited with status {}", output.status)
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

osascript 失败且 stderr 为空时,这里会生成类似 "osascript exited with status exit status: 1" 的重复文案(ExitStatus 的 Display 已包含 "exit status:")。建议改为基于 output.status.code() 组装更清晰的错误原因,或直接格式化 output.status 而不要再额外加 "exited with status" 前缀。

Suggested change
format!("osascript exited with status {}", output.status)
if let Some(code) = output.status.code() {
format!("osascript exited with code {}", code)
} else {
format!("osascript failed with status {}", output.status)
}

Copilot uses AI. Check for mistakes.
@BiboyQG BiboyQG marked this pull request as draft April 24, 2026 15:07
@BiboyQG BiboyQG marked this pull request as ready for review April 24, 2026 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants