← 返回 Skills 市场
chordlini

Localsend

作者 Chordlini · GitHub ↗ · v3.4.0
cross-platform ⚠ suspicious
738
总下载
0
收藏
0
当前安装
9
版本数
在 OpenClaw 中安装
/install localsend
功能描述
Send and receive files to/from nearby devices using the LocalSend protocol. Trigger with /localsend to get an interactive Telegram menu with real inline butt...
使用说明 (SKILL.md)

LocalSend

Interactive file transfer between devices on the local network using real Telegram inline keyboard buttons. Works with any device running the LocalSend app (Android, iOS, Windows, macOS, Linux).

Install

The localsend-cli is a zero-dependency Python CLI. Install from GitHub:

curl -fsSL https://raw.githubusercontent.com/Chordlini/localsend-cli/master/localsend-cli -o ~/.local/bin/localsend-cli
chmod +x ~/.local/bin/localsend-cli

Full docs: https://github.com/Chordlini/localsend-cli

Requires Python 3.8+ and openssl (for TLS).


Telegram Button Format

All menus MUST use OpenClaw's inline button format. Send buttons alongside your message using this structure:

buttons: [
  [{ "text": "Label", "callback_data": "ls:action" }],
  [{ "text": "Row 2", "callback_data": "ls:other" }]
]
  • Outer array = rows of buttons
  • Inner array = buttons per row (max 3 per row for readability)
  • Prefix all callback_data with ls: to namespace this skill
  • When user taps a button, you receive: callback_data: ls:action

State Awareness (CRITICAL)

This skill uses conversational state. Track where you are in the flow:

State Meaning Next user input should be treated as...
idle No active flow Normal message — respond normally
awaiting_file Asked user to drop/specify a file to send The file to send — do NOT comment on it, describe it, or react to it. Immediately use it as the send payload.
awaiting_text Asked user to type text to send The text payload — send it, don't discuss it
awaiting_confirm Waiting for send confirmation Expect ls:confirm-send or ls:menu
receiving Receiver is active Monitor for incoming files

RULES:

  • When in awaiting_file state and user sends an image/file/path → treat it as the file to send. Show confirmation buttons immediately.
  • When in awaiting_text state and user types anything → treat it as the text to send.
  • NEVER comment on, describe, or react to a file/image when you're in awaiting_file state.
  • State resets to idle when user taps ls:menu or the flow completes.

On Trigger: Main Menu

When the user types /localsend or mentions sending/receiving files locally, send this message with real inline buttons:

Message:

📡 LocalSend — File Transfer

Buttons:

buttons: [
  [
    { "text": "📤 Send", "callback_data": "ls:send" },
    { "text": "📥 Receive", "callback_data": "ls:receive" }
  ],
  [
    { "text": "🔍 Scan Devices", "callback_data": "ls:devices" }
  ]
]

Do NOT run any commands yet. Wait for the button tap.


Flow: Scan Devices

Trigger: callback_data: ls:devices or user says "scan", "discover", "find devices"

  1. Run:

    localsend-cli discover --json -t 2
    
  2. Devices found — create one button per device, plus Refresh and Back:

    Message:

    📡 Found 3 devices:
    

    Buttons (one device per row):

    buttons: [
      [{ "text": "📱 Fast Potato — 192.168.0.148", "callback_data": "ls:dev:Fast Potato" }],
      [{ "text": "💻 Rami-Desktop — 192.168.0.100", "callback_data": "ls:dev:Rami-Desktop" }],
      [{ "text": "🖥️ Living Room PC — 192.168.0.105", "callback_data": "ls:dev:Living Room PC" }],
      [
        { "text": "🔄 Refresh", "callback_data": "ls:devices" },
        { "text": "⬅️ Back", "callback_data": "ls:menu" }
      ]
    ]
    
  3. No devices found:

    Message:

    📡 No devices found.
    Make sure LocalSend is open on the other device and both are on the same WiFi.
    

    Buttons:

    buttons: [
      [
        { "text": "🔄 Try Again", "callback_data": "ls:devices" },
        { "text": "⬅️ Back", "callback_data": "ls:menu" }
      ]
    ]
    
  4. User taps a device (callback_data: ls:dev:DEVICENAME) — store it as the selected target. Show action menu:

    Message:

    ✅ Selected: Fast Potato (192.168.0.148)
    What do you want to do?
    

    Buttons:

    buttons: [
      [
        { "text": "📄 Send File", "callback_data": "ls:sendfile" },
        { "text": "📝 Send Text", "callback_data": "ls:sendtext" }
      ],
      [
        { "text": "📦 Send Multiple", "callback_data": "ls:sendmulti" },
        { "text": "⬅️ Back", "callback_data": "ls:devices" }
      ]
    ]
    

Flow: Send

Trigger: callback_data: ls:send

Step 1 — Pick target device (if not already selected)

Run discover and show device picker (see Scan Devices flow above).

Step 2 — Choose what to send

Message:

Send to Fast Potato:

Buttons:

buttons: [
  [
    { "text": "📄 Send File", "callback_data": "ls:sendfile" },
    { "text": "📝 Send Text", "callback_data": "ls:sendtext" }
  ],
  [
    { "text": "📦 Send Multiple", "callback_data": "ls:sendmulti" },
    { "text": "⬅️ Back", "callback_data": "ls:menu" }
  ]
]

Send File (callback_data: ls:sendfile)

  1. Ask: "Send me the file, drop a path, or tell me which file to send"

  2. User provides file path or sends a file via chat

  3. Get file size with stat or ls -lh

  4. Confirm with buttons:

    Message:

    📤 Send to Fast Potato?
    📄 project.zip — 4.2 MB
    

    Buttons:

    buttons: [
      [
        { "text": "✅ Send", "callback_data": "ls:confirm-send" },
        { "text": "❌ Cancel", "callback_data": "ls:menu" }
      ]
    ]
    
  5. On confirm, run:

    localsend-cli send --to "Fast Potato" /path/to/project.zip
    
  6. Report result:

    Message:

    ✅ Sent project.zip (4.2 MB) to Fast Potato
    

    Buttons:

    buttons: [
      [
        { "text": "📤 Send Another", "callback_data": "ls:send" },
        { "text": "⬅️ Menu", "callback_data": "ls:menu" }
      ]
    ]
    

Send Text (callback_data: ls:sendtext)

  1. Ask: "Type the text you want to send:"

  2. User types their message

  3. Write text to temp file, send:

    echo "user's text" > /tmp/localsend-text.txt
    localsend-cli send --to "Fast Potato" /tmp/localsend-text.txt
    rm /tmp/localsend-text.txt
    
  4. Confirm:

    Message:

    ✅ Text sent to Fast Potato
    

    Buttons:

    buttons: [
      [
        { "text": "📝 Send More Text", "callback_data": "ls:sendtext" },
        { "text": "📤 Send File", "callback_data": "ls:sendfile" }
      ],
      [{ "text": "⬅️ Menu", "callback_data": "ls:menu" }]
    ]
    

Send Multiple (callback_data: ls:sendmulti)

  1. Ask: "List the files or give me a glob pattern (e.g. ~/Screenshots/*.png)"

  2. User provides paths or pattern

  3. Expand glob, list files with sizes:

    Message:

    📦 Send 5 files to Fast Potato?
    📄 photo1.jpg — 2.1 MB
    📄 photo2.jpg — 1.8 MB
    📄 photo3.jpg — 3.2 MB
    📄 photo4.jpg — 2.5 MB
    📄 photo5.jpg — 1.9 MB
    📊 Total: 11.5 MB
    

    Buttons:

    buttons: [
      [
        { "text": "✅ Send All", "callback_data": "ls:confirm-send" },
        { "text": "❌ Cancel", "callback_data": "ls:menu" }
      ]
    ]
    
  4. On confirm, run:

    localsend-cli send --to "Fast Potato" photo1.jpg photo2.jpg photo3.jpg photo4.jpg photo5.jpg
    
  5. Report:

    Message:

    ✅ Sent 5 files (11.5 MB) to Fast Potato
    

    Buttons:

    buttons: [
      [
        { "text": "📤 Send More", "callback_data": "ls:send" },
        { "text": "⬅️ Menu", "callback_data": "ls:menu" }
      ]
    ]
    

Flow: Receive

Trigger: callback_data: ls:receive or user says "receive", "start receiving", "listen"

Step 1 — Snapshot current files

ls -1 /home/rami/.openclaw/workspace/_incoming/ > /tmp/localsend-before.txt

Step 2 — Start receiver in background

localsend-cli --alias openclaw-workspace receive --save-dir /home/rami/.openclaw/workspace/_incoming/ -y

Run with run_in_background: true. Store the task ID.

CRITICAL: --alias MUST come BEFORE receive (global flag).

Step 3 — Confirm ready with buttons

Message:

📡 Receiver active — "openclaw-workspace"
📁 Saving to: ~/incoming/
✅ Auto-accept: ON

Send files from your device whenever ready.

Buttons:

buttons: [
  [
    { "text": "🛑 Stop", "callback_data": "ls:stop" },
    { "text": "🔄 Status", "callback_data": "ls:status" }
  ]
]

Step 4 — Monitor for incoming files

Poll every 3 seconds for new files:

ls -1 /home/rami/.openclaw/workspace/_incoming/ > /tmp/localsend-after.txt
diff /tmp/localsend-before.txt /tmp/localsend-after.txt

Step 5 — Post-receive confirmation (MANDATORY)

When file(s) arrive, immediately present in chat with inline buttons.

Single file:

Message:

✅ Received from Fast Potato:
📄 portfolio.zip — 240 MB
📁 Saved to: ~/incoming/portfolio.zip

Buttons (contextual by file type):

buttons: [
  [
    { "text": "📂 Extract", "callback_data": "ls:extract" },
    { "text": "🚀 Deploy", "callback_data": "ls:deploy" }
  ],
  [
    { "text": "📥 Receive More", "callback_data": "ls:receive" },
    { "text": "🛑 Stop", "callback_data": "ls:stop" }
  ]
]

Image file — show inline preview:

Message:

✅ Received from Fast Potato:
🖼️ screenshot.png — 2.1 MB

Include MEDIA:~/incoming/screenshot.png for inline preview.

Buttons:

buttons: [
  [
    { "text": "📂 Open Folder", "callback_data": "ls:openfolder" },
    { "text": "📥 Receive More", "callback_data": "ls:receive" }
  ],
  [{ "text": "🛑 Stop", "callback_data": "ls:stop" }]
]

Multiple files:

Message:

✅ Received 3 files from Fast Potato:
📄 app.apk — 45 MB
📄 README.md — 2 KB
🖼️ icon.png — 128 KB
📊 Total: 45.1 MB

Buttons:

buttons: [
  [
    { "text": "📂 Show All", "callback_data": "ls:showall" },
    { "text": "📥 Receive More", "callback_data": "ls:receive" }
  ],
  [{ "text": "🛑 Stop", "callback_data": "ls:stop" }]
]

Contextual button rules by file type:

  • .zip, .tar.gz → add 📂 Extract button
  • .png, .jpg, .gif, .webp → show MEDIA: inline + 📂 Open Folder
  • .apk → add 📱 Install button
  • .html, .js, .py → add 👁️ Preview button
  • website archives → add 🚀 Deploy button

Step 6 — Stop receiver

Trigger: callback_data: ls:stop

  1. Kill the background task using stored task ID

  2. Confirm:

    Message:

    🛑 Receiver stopped.
    

    Buttons:

    buttons: [
      [
        { "text": "📡 Restart", "callback_data": "ls:receive" },
        { "text": "⬅️ Menu", "callback_data": "ls:menu" }
      ]
    ]
    

Flow: Status Check

Trigger: callback_data: ls:status

Check if receiver is running and count new files:

ls -1 /home/rami/.openclaw/workspace/_incoming/ > /tmp/localsend-after.txt
diff /tmp/localsend-before.txt /tmp/localsend-after.txt | grep "^>" | wc -l

Message:

📡 Receiver: Running (12 min)
📁 Files received: 2
📊 Total: 242 MB

Buttons:

buttons: [
  [
    { "text": "🛑 Stop", "callback_data": "ls:stop" },
    { "text": "📂 Show Files", "callback_data": "ls:showall" }
  ]
]

Callback Data Reference

callback_data Action
ls:menu Show main menu
ls:send Start send flow
ls:receive Start receive flow
ls:devices Discover devices
ls:dev:DEVICENAME Select a specific device
ls:sendfile Send single file
ls:sendtext Send text message
ls:sendmulti Send multiple files
ls:confirm-send Confirm and execute send
ls:stop Stop receiver
ls:status Check receiver status
ls:extract Extract received archive
ls:deploy Deploy received website
ls:openfolder Open save directory
ls:showall List all received files

CLI Reference

Command Usage
Discover localsend-cli discover --json -t 2
Send localsend-cli send --to "DEVICE" file1 file2 ...
Receive localsend-cli --alias NAME receive --save-dir DIR -y
Flag Scope Description
--alias NAME Global (before subcommand) Device name to advertise
--to NAME send Target device (case-insensitive substring)
-t N discover Scan duration in seconds (use 2 for speed)
--json discover Machine-readable output
--save-dir DIR receive Save location (default: ~/Downloads)
-y receive Auto-accept transfers

Troubleshooting

Problem Fix
unrecognized arguments: --alias Move --alias BEFORE the subcommand
No devices found Open LocalSend on target, same WiFi, screen on
Port 53317 in use Normal — CLI auto-falls back to 53318/53319
Transfer declined (403) Use -y on receiver side
Transfer hangs Large file on slow WiFi — be patient

Reference

安全使用建议
This skill appears to do what it claims: discover local devices and send/receive files. Before installing/using it, verify the localsend-cli binary you install (prefer official releases, check checksum/signature) rather than blindly running curl|sh. Be aware the agent will run local commands (stat/ls) and will transmit any file you supply to the selected local device — do not send sensitive files unless you trust the recipient and the local network. The protocol notes that devices use self-signed TLS certs and skip verification; this is common for LAN tools but makes MITM possible on untrusted networks, so avoid using it on public or hostile networks.
功能分析
Type: OpenClaw Skill Name: localsend Version: 3.4.0 The skill bundle is suspicious due to multiple shell injection vulnerabilities identified in `SKILL.md`. User-provided file paths, text content, and glob patterns are directly interpolated into shell commands (e.g., `localsend-cli send`, `echo`), creating critical Remote Code Execution (RCE) risks if not properly sanitized by the agent. Additionally, the `curl` based installation method for `localsend-cli` introduces a supply chain vulnerability by fetching and executing a remote script from GitHub, which could be compromised. These issues represent significant security flaws rather than explicit malicious intent.
能力评估
Purpose & Capability
Name/description, required binaries (localsend-cli, openssl), and the actions described (device discovery, prepare/upload flows) are coherent: a LocalSend client legitimately needs a CLI and TLS support.
Instruction Scope
SKILL.md tells the agent to run localsend-cli discover/prepare/upload and to call local shell commands (stat/ls -lh) to measure file size. It also instructs the agent to accept files/paths from the user and immediately send them (do not comment on file contents). These behaviors are expected for a file-transfer skill, but they mean the agent will access local files and send them on the local network — users should be aware that any file they provide will be transmitted as-is.
Install Mechanism
The skill is instruction-only (no install spec executed automatically), which is low-risk. However the README suggests installing localsend-cli via a curl from a raw GitHub URL; fetching and running scripts from raw URLs is a common pattern but carries supply-chain risk. Prefer installing from an official release/archive or verifying checksums/signatures.
Credentials
No environment variables or unrelated credentials are requested. The skill does not ask for unrelated tokens or system config paths.
Persistence & Privilege
Skill does not request always:true, does not modify other skills, and has no install-time persistence specified. It operates only when invoked.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install localsend
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /localsend 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v3.4.0
- Updated install instructions: now uses direct download from the GitHub repo for the latest `localsend-cli`. - Referenced official CLI documentation link for further help. - Clarified that `localsend-cli` is a zero-dependency Python CLI, not just a bundled script. - No changes to flows, buttons, or state logic.
v3.3.0
**LocalSend 3.3.0 Changelog** - Added install instructions to SKILL.md for the bundled `localsend-cli` script. - Metadata now specifies an installation step for `localsend-cli`, ensuring it is copied and made executable if needed. - Declared Python 3.8+ and `openssl` as required dependencies. - No changes to core menu flows or protocol behavior—this release focuses on simplifying initial setup.
v3.2.0
**Version 3.2.0 — Adds robust conversational state tracking for reliable file transfers** - Introduced explicit state management (idle, awaiting_file, awaiting_text, awaiting_confirm, receiving) to accurately track user interactions. - CRITICAL: No longer reacts to, describes, or comments on files or images when awaiting a file payload — immediately processes send actions. - Updated device discovery timeout from 5 seconds to 2 seconds for a snappier device scan. - Clarified and enforced unambiguous state transitions and button handling in the documentation. - Ensured user input is always treated as the correct payload in the expected flow, reducing user friction and errors.
v3.1.0
Real Telegram inline keyboard buttons — full interactive menu with device picker, send/receive flows, contextual file-type buttons, and callback routing
v3.0.0
Real Telegram inline keyboard buttons for all menus, device picker, send/receive flows, and contextual actions
v2.0.0
Full interactive menu: /localsend trigger, device picker with select, send file/text/multiple, receive with inline confirmation, contextual action buttons, refresh/status
v1.2.0
Post-receive confirmation: files presented in chat with details, inline image preview, and contextual action buttons
v1.1.0
v1.1.0: Telegram inline buttons (discover/send/receive menus), fixed --alias flag ordering (global flag must come before subcommand), background receive pattern, real-world examples, improved troubleshooting table
v1.0.0
Initial release — send and receive files between devices via LocalSend protocol
元数据
Slug localsend
版本 3.4.0
许可证
累计安装 0
当前安装数 0
历史版本数 9
常见问题

Localsend 是什么?

Send and receive files to/from nearby devices using the LocalSend protocol. Trigger with /localsend to get an interactive Telegram menu with real inline butt... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 738 次。

如何安装 Localsend?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install localsend」即可一键安装,无需额外配置。

Localsend 是免费的吗?

是的,Localsend 完全免费(开源免费),可自由下载、安装和使用。

Localsend 支持哪些平台?

Localsend 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Localsend?

由 Chordlini(@chordlini)开发并维护,当前版本 v3.4.0。

💬 留言讨论