--- name: proton-drive description: Hermes skill for Proton Drive — list, read, upload, download, search, and manage files using the rclone protondrive backend. version: 1.0.0 author: Trentuna / Bee license: MIT platforms: [linux, macos, windows] metadata: hermes: tags: [proton, drive, cloud-storage, rclone, file-management] related_skills: [proton-mail, proton-pass, proton-vpn] required_environment_variables: - PROTON_RCLONE_REMOTE optional_environment_variables: - PROTON_RCLONE_PATH - PROTON_DRIVE_USE_SDK --- # Proton Drive Skill > Agents can read, write, search, and manage files on Proton Drive through > the battle-tested [rclone protondrive backend](https://rclone.org/protondrive/). ## Prerequisites ### 1. Install rclone ```bash # Linux (official script) curl https://rclone.org/install.sh | sudo bash # macOS brew install rclone # Verify rclone version ``` ### 2. Configure the protondrive remote ```bash rclone config create protondrive protondrive \ username=your@proton.me \ password=your_password \ --non-interactive ``` Or interactively: ```bash rclone config # → Choose "n" (new remote) # → Name: protondrive # → Type: protondrive # → Follow prompts for username, password, 2FA ``` ### 3. Set environment variables (optional) ```bash export PROTON_RCLONE_REMOTE=protondrive # default: protondrive export PROTON_RCLONE_PATH=/path/to/rclone # default: auto-detect from PATH ``` On first run, rclone will prompt for the mailbox password (your Proton login password). After authentication, tokens are cached locally by rclone's own credential store — no additional auth management needed for subsequent calls. ## Tools The skill provides 9 tools for interacting with Proton Drive. Each tool shells out to `rclone` with the configured protondrive remote. ### `proton_drive_list` List files and folders in a path on Proton Drive. ``` Usage: rclone lsf --json : Args: path (string, default: "/") — Path to list (e.g. "Documents" or "/") recursive (bool, default: false) — List recursively dirs_only (bool, default: false) — Show directories only files_only (bool, default: false) — Show files only Returns: JSON array of {Name, Path, Size, ModTime, IsDir} items ``` ### `proton_drive_read` Read a file's content from Proton Drive. ``` Usage: rclone cat : Args: path (string, required) — Path to the file (e.g. "Documents/notes.txt") head (int, optional) — Only read first N lines tail (int, optional) — Only read last N lines Returns: File content as text string (up to 10MB; larger files use download instead) ``` Large files (>10MB) should be downloaded rather than read inline. The tool will return an error suggesting `proton_drive_download` for files exceeding the size threshold. ### `proton_drive_download` Download a file from Proton Drive to a local path. ``` Usage: rclone copy : Args: remote_path (string, required) — Source path on Drive (e.g. "Documents/report.pdf") local_path (string, required) — Destination local path (absolute or ~/expanded) progress (bool, default: false) — Show transfer progress Returns: JSON with {status, local_path, size_bytes} ``` The local path must be writable. If the path ends with `/`, the file is downloaded into that directory preserving its filename. ### `proton_drive_upload` Upload a local file or directory to Proton Drive. ``` Usage: rclone copy : Args: local_path (string, required) — Source path on local filesystem remote_path (string, required) — Destination path on Drive (e.g. "Documents/") create_parents (bool, default: true) — Create parent dirs if they don't exist progress (bool, default: false) — Show transfer progress Returns: JSON with {status, remote_path, size_bytes} ``` Supports both individual files and entire directories. ### `proton_drive_search` Search for files by name across Proton Drive. ``` Usage: rclone lsf -R --files-only : | grep -i OR (for structured results): rclone lsf -R --json : | jq Args: query (string, required) — Search term or regex pattern path (string, default: "/") — Root path to search under regex (bool, default: false) — Treat query as regex instead of substring max_results (int, default: 50) — Max results to return Returns: JSON array of matching {Name, Path, Size, ModTime} ``` ### `proton_drive_mkdir` Create a folder on Proton Drive. ``` Usage: rclone mkdir : Args: path (string, required) — Path of folder to create (e.g. "Documents/NewFolder") Returns: JSON with {status: "created", path} ``` Creates all parent directories if they don't exist (like `mkdir -p`). ### `proton_drive_delete` Delete a file or empty folder from Proton Drive. ``` Usage: rclone delete : Args: path (string, required) — Path to the file/folder to delete recursive (bool, default: false) — Recursively delete folder contents Returns: JSON with {status: "deleted", path} ``` Non-recursive deletion of non-empty folders will fail. rclone's `purge` command is used for recursive deletes. ### `proton_drive_stat` Get detailed metadata for a file or folder. ``` Usage: rclone lsl : OR (detailed): rclone lsf --json : Args: path (string, required) — Path to the file or folder Returns: JSON with {Name, Path, Size, ModTime, IsDir, Hash, MimeType} ``` ### `proton_drive_sync` Synchronize a local directory with Proton Drive (or vice versa). ``` Usage: rclone sync [flags] Args: source (string, required) — Source path (local: or remote:) dest (string, required) — Destination (local: or remote:) direction (enum, default: "upload") — "upload" (local→Drive), "download" (Drive→local), "bidirectional" dry_run (bool, default: true) — If true, show what would change without syncing delete_excluded (bool, default: false) — Delete files at dest not present at source Returns: JSON with {status, changed, added, deleted, errors} ``` **IMPORTANT:** Defaults to `dry_run=true` for safety. The agent MUST confirm with the user before running a live sync, especially when `delete_excluded=true` — this can cause data loss. ## Implementation All tools are implemented as Python subprocess wrappers in the `tools/` subdirectory. The primary backend is `rclone`; the TypeScript Drive SDK is available as a fallback via `PROTON_DRIVE_USE_SDK=true`. ### Tool Handler Pattern ```python def handle_proton_drive_list(args: dict, **kwargs) -> dict: path = args.get("path", "/") recursive = args.get("recursive", False) cmd = _build_rclone_command("lsf", "--json", path, recursive=recursive) result = _run_rclone(cmd, timeout=30) if result.returncode != 0: return {"error": result.stderr.strip()} items = [json.loads(line) for line in result.stdout.strip().split("\n") if line] return {"items": items} ``` ### Rclone Configuration Check Before any tool execution, verify the rclone remote exists: ```python def _check_rclone_remote(remote: str) -> bool: result = subprocess.run( ["rclone", "listremotes"], capture_output=True, text=True, timeout=5 ) return f"{remote}:" in result.stdout ``` If the remote is not configured, return a clear error with setup instructions referencing the README. ## Error Handling | Error | Cause | Resolution | |-------|-------|------------| | `remote not found` | protondrive remote not configured | Run `rclone config` or refer to README | | `authentication required` | Token expired or invalid | Run `rclone config reconnect ` | | `file not found` | Path doesn't exist | Check path with `proton_drive_list` | | `file too large` | Read attempt on >10MB file | Use `proton_drive_download` instead | | `rate limited` | Too many API calls | Retry with backoff (rclone does this auto) | ## Security Notes - Files read by `proton_drive_read` enter the agent's context. For sensitive documents, prefer `proton_drive_download` and specify a local path. - `proton_drive_sync` with `delete_excluded=true` is destructive. Always default to `dry_run=true` and require confirmation. - rclone stores tokens in its config file (`~/.config/rclone/rclone.conf`). Ensure this file has appropriate file permissions (`chmod 600`).