perkoon-transfer

The agent data layer. Perkoon moves files between agents and the physical world — agent to human, agent to agent, agent to pipeline. P2P over WebRTC. Free. Encrypted. Unlimited. No accounts. Files never touch our servers. CLI, MCP server, A2A protocol, browser automation — pick the interface that fits your runtime.

3,891 stars

Best use case

perkoon-transfer is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

The agent data layer. Perkoon moves files between agents and the physical world — agent to human, agent to agent, agent to pipeline. P2P over WebRTC. Free. Encrypted. Unlimited. No accounts. Files never touch our servers. CLI, MCP server, A2A protocol, browser automation — pick the interface that fits your runtime.

Teams using perkoon-transfer should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/perkoon-transfer/SKILL.md --create-dirs "https://raw.githubusercontent.com/openclaw/skills/main/skills/alex-vy/perkoon-transfer/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/perkoon-transfer/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How perkoon-transfer Compares

Feature / Agentperkoon-transferStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

The agent data layer. Perkoon moves files between agents and the physical world — agent to human, agent to agent, agent to pipeline. P2P over WebRTC. Free. Encrypted. Unlimited. No accounts. Files never touch our servers. CLI, MCP server, A2A protocol, browser automation — pick the interface that fits your runtime.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Perkoon — The Agent Data Layer

File transfer for humans and the things replacing them.

Your agent has compute, memory, and context. What it lacks is a jump gate to the physical world. Perkoon is that gate — P2P file transfer over WebRTC, engineered for autonomous machines from day one.

Not "AI-ready" the way a gas station is gourmet-ready. Actually built for machines — JSON event streams, structured exit codes, MCP native tools, an A2A protocol endpoint, and a state machine that doesn't need a browser, a mouse, or a soul.

**Four integration methods — pick the one that fits your runtime:**

| Method | Best for | Install size |
|--------|----------|-------------|
| **MCP Server** | Coding agents (Claude Code, Cursor, Windsurf, VS Code Copilot) | ~8 MB |
| **CLI** | Agents with shell access | ~8 MB |
| **A2A Protocol** | Agents with HTTP but no shell (ChatGPT, web agents) | Zero — just POST |
| **Browser Automation** | Full UI control via Playwright/Puppeteer | ~200 MB (Chromium) |

**Three supported flight paths:**
- **Agent → Human**: Your agent sends a file. The human opens a link in any browser. No install on their end.
- **Agent → Agent**: CLI to CLI, MCP to MCP, or A2A to A2A. Two machines, no humans in the loop.
- **Agent → Pipeline**: Stream received files to stdout, pipe into processing. No disk writes required.

P2P transfers are free, unlimited, and encrypted. Both ends need to be online — that's the only constraint. For sensitive files, always use `--password` — without it, anyone with the share link can download.

---

## METHOD 1: MCP Server (recommended for coding agents)

If your host supports MCP, this is the fastest path. Three native tools, zero shell commands.

Install: `npx -y @perkoon/mcp@0.1.3` (stdio transport, pinned version)

**Tools provided:**
- `send_file` — Send a file. Returns session code + share URL. Waits for receiver.
- `receive_file` — Receive files from a session code. Saves to disk.
- `check_session` — Check if a session is active, expired, or not found.

Configuration for common hosts:

```json
{
  "mcpServers": {
    "perkoon": {
      "command": "npx",
      "args": ["-y", "@perkoon/mcp@0.1.3"]
    }
  }
}
```

- **Claude Code**: Add to `.mcp.json` in your project
- **Claude Desktop**: Add to `claude_desktop_config.json`
- **Cursor / VS Code / Windsurf**: Settings → MCP → Add Server → `npx -y @perkoon/mcp@0.1.3`

Once configured, just call the tools directly — no bash, no log polling, no background processes.

---

## METHOD 2: CLI (for agents with shell access)

**IMPORTANT**: Use `npx -y perkoon@0.3.6` (pinned version) to avoid dynamic fetching of unaudited code.

### SENDING a file

#### Step 1: Confirm the file path with the user, then start send

Before sending, confirm the file path and name with the user. Do not send files from sensitive directories without explicit user approval.

Replace `/path/to/file` with the actual file path:

```bash
rm -f /tmp/perkoon-send.log /tmp/perkoon-send.pid
npx -y perkoon@0.3.6 send /path/to/file --json --timeout 1800 > /tmp/perkoon-send.log 2>&1 &
echo $! > /tmp/perkoon-send.pid

# Wait for session code (up to 30s)
for i in $(seq 1 30); do
  if grep -q session_created /tmp/perkoon-send.log 2>/dev/null; then
    grep session_created /tmp/perkoon-send.log
    break
  fi
  if grep -q '"event":"error"' /tmp/perkoon-send.log 2>/dev/null; then
    echo "===SEND FAILED===" && cat /tmp/perkoon-send.log
    break
  fi
  sleep 1
done
```

Output: `{"event":"session_created","session_code":"K7MX4QPR9W2N","share_url":"https://perkoon.com/K7MX4QPR9W2N"}`

Once `session_created` appears, share the URL with the user. Example: "Here's your file — open this link on any device to download it: https://perkoon.com/K7MX4QPR9W2N"

The receiver doesn't need to install anything. The link works in any browser.

For password-protected sends, add `--password SECRET` and share both the URL and password.

#### Step 2: Monitor until complete — then REPORT BACK

You MUST run this after sharing the link. Do NOT skip this step.

```bash
for i in $(seq 1 360); do
  if grep -q transfer_complete /tmp/perkoon-send.log 2>/dev/null; then
    echo "===TRANSFER COMPLETE===" && grep transfer_complete /tmp/perkoon-send.log
    break
  fi
  if grep -q '"event":"error"' /tmp/perkoon-send.log 2>/dev/null; then
    echo "===TRANSFER FAILED===" && grep error /tmp/perkoon-send.log
    break
  fi
  if [ "$((i % 30))" -eq 0 ]; then
    grep progress /tmp/perkoon-send.log 2>/dev/null | tail -1
  fi
  sleep 5
done
```

- **`===TRANSFER COMPLETE===`** → Tell the user: "File sent successfully!" Include speed and duration from the JSON.
- **`===TRANSFER FAILED===`** → Tell the user what went wrong.
- **You MUST tell the user the outcome. Never finish silently.**

### SENDING into a pre-created session (Agent → Agent)

When another agent creates a session via A2A and gives you a session code + sender key:

```bash
rm -f /tmp/perkoon-send.log /tmp/perkoon-send.pid
npx -y perkoon@0.3.6 send /path/to/file --session CODE --sender-key KEY --json --timeout 1800 > /tmp/perkoon-send.log 2>&1 &
echo $! > /tmp/perkoon-send.pid
```

Then monitor with the same Step 2 above. This joins an existing session as sender instead of creating a new one. The receiving agent runs `npx -y perkoon@0.3.6 receive CODE --json` on their end.

### RECEIVING a file

Replace `CODE` with the 12-character session code:

```bash
rm -f /tmp/perkoon-recv.log /tmp/perkoon-recv.pid
npx -y perkoon@0.3.6 receive CODE --json --overwrite --output /home/openclaw/.openclaw/workspace/received/ > /tmp/perkoon-recv.log 2>&1 &
echo $! > /tmp/perkoon-recv.pid

for i in $(seq 1 360); do
  if grep -q transfer_complete /tmp/perkoon-recv.log 2>/dev/null; then
    echo "===TRANSFER COMPLETE===" && grep transfer_complete /tmp/perkoon-recv.log
    break
  fi
  if grep -q '"event":"error"' /tmp/perkoon-recv.log 2>/dev/null; then
    echo "===TRANSFER FAILED===" && grep error /tmp/perkoon-recv.log
    break
  fi
  sleep 5
done
```

For password-protected sessions, add `--password SECRET`.

- **`===TRANSFER COMPLETE===`** → Tell the user: "File received!" and the save path.
- **`===TRANSFER FAILED===`** → Tell the user what went wrong.
- **You MUST tell the user the outcome. Never finish silently.**

Files are saved to `/home/openclaw/.openclaw/workspace/received/`.

### Pipe to stdout

Stream a received file directly into another process — no disk write:

```bash
npx -y perkoon@0.3.6 receive CODE --output - > /path/to/destination
```

---

## METHOD 3: A2A Protocol (for agents with HTTP, no shell)

If you can make HTTP requests but can't run shell commands, use the A2A endpoint directly.

**Endpoint:** `POST https://perkoon.com/a2a`
**Protocol:** JSON-RPC 2.0
**Agent Card:** `https://perkoon.com/.well-known/agent.json`

### Discover capabilities

```json
{
  "jsonrpc": "2.0",
  "method": "message/send",
  "id": "1",
  "params": {
    "message": {
      "parts": [{ "type": "data", "data": { "skill": "describe" } }]
    }
  }
}
```

### Create a send session

```json
{
  "jsonrpc": "2.0",
  "method": "message/send",
  "id": "1",
  "params": {
    "message": {
      "parts": [{
        "type": "data",
        "data": {
          "skill": "send-files",
          "name": "quarterly-report"
        }
      }]
    }
  }
}
```

Returns `sender_url` (for browser upload) + CLI commands + `sender_key` for A2A sender joining.

If you have shell access, run the CLI command from the response. If not, share the `sender_url` with your user — they open it in any browser to upload.

### Join a session as receiver

```json
{
  "jsonrpc": "2.0",
  "method": "message/send",
  "id": "1",
  "params": {
    "message": {
      "parts": [{
        "type": "data",
        "data": {
          "skill": "receive-files",
          "session_code": "K7MX4QPR9W2N"
        }
      }]
    }
  }
}
```

### Check session status

```json
{
  "jsonrpc": "2.0",
  "method": "message/send",
  "id": "1",
  "params": {
    "message": {
      "parts": [{
        "type": "data",
        "data": {
          "skill": "session-status",
          "session_code": "K7MX4QPR9W2N"
        }
      }]
    }
  }
}
```

### Runtime hints

Include `clientCapabilities` in your DataPart to get optimized instructions:

```json
{
  "type": "data",
  "data": {
    "skill": "send-files",
    "clientCapabilities": { "shellAccess": true, "nodeJs": true }
  }
}
```

Agents declaring shell access get CLI commands. Web-only agents get browser URLs.

---

## METHOD 4: Browser Automation (Playwright/Puppeteer)

For agents that need full browser UI control. Heavier than CLI but gives visual verification.

**Ready-to-run scripts** (requires `npm install playwright`):

```bash
curl https://perkoon.com/perkoon_send.mjs > send.mjs && node send.mjs /path/to/file.zip
curl https://perkoon.com/perkoon_receive.mjs > receive.mjs && node receive.mjs SESSION_CODE ./output
```

### Manual sender flow

1. Navigate to `https://perkoon.com/create`, accept TOS, click Start
2. Skip confirmation modals: `localStorage.setItem('perkoon_skip_confirm_direct-confirm', 'true')` and `localStorage.setItem('perkoon_skip_confirm_staged-confirm', 'true')`
3. Add files: `page.setInputFiles('[data-testid="file-input"]', filePath)`
4. Share session code with recipient
5. Wait for receiver: `page.waitForFunction(() => window.__perkoon?.participants?.length >= 2, null, { timeout: 300000 })`
6. Click `[data-testid="start-transfer"]`
7. Wait: `page.waitForFunction(() => window.__perkoon?.transfer?.status === 'complete', null, { timeout: 600000 })`

### Manual receiver flow

1. Register download handler: `page.on('download', d => downloads.push(d))`
2. Navigate to `https://perkoon.com/{SESSION_CODE}?agent=true`
3. Accept transfer: wait for `[data-testid="transfer-accept"]`, click `[data-testid="transfer-tos-checkbox"]` if visible, then click `[data-testid="transfer-accept"]`
4. Wait: `page.waitForFunction(() => window.__perkoon?.transfer?.status === 'complete', null, { timeout: 600000 })`
5. Save: `await download.saveAs('./received/' + basename(download.suggestedFilename()))`

---

## CLI reference

| Flag | Description |
|------|-------------|
| `--json` | Machine-readable JSON events (always use for automation) |
| `--session <code>` | Join an existing session as sender (A2A agent-to-agent) |
| `--sender-key <key>` | Auth key for `--session` (provided by session creator) |
| `--password <pw>` | End-to-end password protection |
| `--timeout <sec>` | Peer wait time (default: 300, use 1800 for sends) |
| `--output <dir>` | Save directory (default: ./received) |
| `--output -` | Stream to stdout (no disk write) |
| `--overwrite` | Replace existing files |
| `--quiet` | Suppress human-readable output |

## JSON event stream

Events appear in order on stdout when using `--json`:

| Event | Meaning | Key fields |
|-------|---------|------------|
| `session_created` | Ready — share the link now | `session_code`, `share_url` |
| `receiver_connected` | Peer joined | |
| `webrtc_connected` | Direct P2P link established | |
| `progress` | Transfer in progress | `percent`, `speed`, `eta` |
| `transfer_complete` | Done | `duration_ms`, `speed` |
| `error` | Failed | `message`, `exit_code` |

## Exit codes

| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Bad arguments |
| 2 | File not found |
| 3 | Network/session error |
| 4 | Wrong password |
| 5 | Timeout — no peer joined |

## Rules

1. ALWAYS use `--json` for parseable output
2. ALWAYS confirm the file path with the user before sending
3. Once `session_created` appears, share the URL with the user
4. ALWAYS use `--timeout 1800` for sends (30 min for the human to open the link)
5. ALWAYS use `--overwrite` for receives
6. ALWAYS monitor until `transfer_complete` or `error` — then **tell the user the result**
7. NEVER kill the process mid-transfer
8. The receiver does NOT need perkoon installed — the browser link works for everyone
9. Use pinned versions: `npx -y perkoon@0.3.6` — never use `@latest`
10. NEVER send files from sensitive directories (~/.ssh, ~/.gnupg, /etc) without explicit user approval

## Discovery endpoints

| URL | What it is |
|-----|-----------|
| `https://perkoon.com/.well-known/agent.json` | A2A agent card (machine-readable capabilities) |
| `https://perkoon.com/llms.txt` | Full agent integration guide |
| `https://perkoon.com/automate` | Human-readable automation docs |
| `https://www.npmjs.com/package/@perkoon/mcp` | MCP server package |
| `https://www.npmjs.com/package/perkoon` | CLI package |

Related Skills

USD1 WLF Transfer Skill

3891
from openclaw/skills

## Description

aws-data-transfer-optimizer

3891
from openclaw/skills

Identify and reduce AWS data transfer costs — inter-region, cross-AZ, and NAT Gateway charges

android-transfer-secure

3891
from openclaw/skills

Securely transfers files from macOS to Android with checksum verification and path validation.

pose-transfer

3891
from openclaw/skills

AI-powered fashion model pose transfer tool. Generate pose variations of a model/product image using reference pose images while keeping clothing and background consistent.

---

3891
from openclaw/skills

name: article-factory-wechat

Content & Documentation

humanizer

3891
from openclaw/skills

Remove signs of AI-generated writing from text. Use when editing or reviewing text to make it sound more natural and human-written. Based on Wikipedia's comprehensive "Signs of AI writing" guide. Detects and fixes patterns including: inflated symbolism, promotional language, superficial -ing analyses, vague attributions, em dash overuse, rule of three, AI vocabulary words, negative parallelisms, and excessive conjunctive phrases.

Content & Documentation

find-skills

3891
from openclaw/skills

Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.

General Utilities

tavily-search

3891
from openclaw/skills

Use Tavily API for real-time web search and content extraction. Use when: user needs real-time web search results, research, or current information from the web. Requires Tavily API key.

Data & Research

baidu-search

3891
from openclaw/skills

Search the web using Baidu AI Search Engine (BDSE). Use for live information, documentation, or research topics.

Data & Research

agent-autonomy-kit

3891
from openclaw/skills

Stop waiting for prompts. Keep working.

Workflow & Productivity

Meeting Prep

3891
from openclaw/skills

Never walk into a meeting unprepared again. Your agent researches all attendees before calendar events—pulling LinkedIn profiles, recent company news, mutual connections, and conversation starters. Generates a briefing doc with talking points, icebreakers, and context so you show up informed and confident. Triggered automatically before meetings or on-demand. Configure research depth, advance timing, and output format. Walking into meetings blind is amateur hour—missed connections, generic small talk, zero leverage. Use when setting up meeting intelligence, researching specific attendees, generating pre-meeting briefs, or automating your prep workflow.

Workflow & Productivity

self-improvement

3891
from openclaw/skills

Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong...', 'Actually...'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.

Agent Intelligence & Learning