Hermes skill wrapping the official pass-cli (Rust binary) for agent use.
Follows the architecture from t_d1c7437e (ARCHITECTURE.md section 4).
Tools:
- Auth: proton_pass_login, proton_pass_logout, proton_pass_auth_status, proton_pass_test
- Vaults: proton_pass_vaults, proton_pass_vault_create, proton_pass_vault_delete
- Items: proton_pass_list, proton_pass_get, proton_pass_search, proton_pass_create,
proton_pass_edit, proton_pass_delete, proton_pass_totp, proton_pass_share_item
- Injection: proton_pass_inject (wraps pass-cli run)
- SSH: proton_pass_ssh_load, proton_pass_ssh_agent_start,
proton_pass_ssh_daemon_{start,status,stop}
- Utility: proton_pass_generate_password
Signed-off-by: Murdock A-Team
621 lines
17 KiB
Markdown
621 lines
17 KiB
Markdown
---
|
|
name: proton-pass
|
|
description: Proton Pass secret management — vaults, items, TOTP, SSH keys, and secret injection via the official pass-cli
|
|
version: 1.0.0
|
|
category: productivity
|
|
platforms: [linux, macos]
|
|
dependencies:
|
|
- pass-cli >= 2.1.0 (official Proton Pass Rust CLI)
|
|
metadata:
|
|
hermes:
|
|
tags: [proton, pass, secrets, passwords, vault, totp, ssh]
|
|
auth: independent — pass-cli manages its own encrypted local session
|
|
limitations:
|
|
- "pass-cli is a separate binary; not bundled with Hermes"
|
|
- "Secrets retrieved into agent context — user should be aware of prompt logging"
|
|
- "Interactive login requires a browser or TTY for credential input"
|
|
- "PAT (personal access token) login recommended for headless/automation use"
|
|
---
|
|
# Proton Pass Hermes Skill
|
|
|
|
A Hermes skill that wraps the official [Proton Pass CLI](https://protonpass.github.io/pass-cli/) (`pass-cli`) for agent use. Provides full vault and item lifecycle management — list vaults, retrieve secrets, search, create, edit, delete, TOTP codes, SSH key injection, and secret-injected command execution.
|
|
|
|
## Installation
|
|
|
|
### Prerequisites
|
|
|
|
The skill shells out to `pass-cli` v2.1.0+ (Rust binary). Install it:
|
|
|
|
```bash
|
|
# Linux/macOS — official installer
|
|
curl -fsSL https://proton.me/download/pass-cli/install.sh | bash
|
|
|
|
# Or build from source (requires Rust toolchain)
|
|
git clone https://github.com/ProtonPass/pass-cli.git
|
|
cd pass-cli && cargo build --release
|
|
cp target/release/pass-cli ~/.local/bin/
|
|
```
|
|
|
|
### Authentication
|
|
|
|
`pass-cli` manages its own encrypted session. Authenticate once:
|
|
|
|
```bash
|
|
# Interactive (prompts for password, TOTP, extra password)
|
|
pass-cli login --interactive your@proton.me
|
|
|
|
# Or personal access token (recommended for automation)
|
|
PROTON_PASS_PERSONAL_ACCESS_TOKEN=pst_xxxx...xxxx::TOKENKEY pass-cli login
|
|
|
|
# Verify auth
|
|
pass-cli info
|
|
```
|
|
|
|
### Verifying Setup
|
|
|
|
```bash
|
|
pass-cli test # connection + auth check
|
|
pass-cli vault list --output json # should show your vaults
|
|
pass-cli item list --output json # should show items
|
|
```
|
|
|
|
## Tools
|
|
|
|
### Auth Tools
|
|
|
|
#### `proton_pass_login`
|
|
|
|
Authenticate with Proton Pass. Three modes:
|
|
|
|
| Mode | Description | When to Use |
|
|
|------|-------------|-------------|
|
|
| `interactive` | Prompts for password, TOTP, extra password | Initial setup, interactive sessions |
|
|
| `pat` | Personal access token | CI/CD, headless, automation |
|
|
| `web` | Browser-based OAuth | SSO, hardware key support |
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_login",
|
|
"description": "Authenticate with Proton Pass.",
|
|
"parameters": {
|
|
"properties": {
|
|
"mode": { "type": "string", "enum": ["interactive", "pat", "web"] },
|
|
"username": { "type": "string", "description": "Proton account email" },
|
|
"token": { "type": "string", "description": "PAT token (pat mode only)" }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:**
|
|
- Interactive: `pass-cli login --interactive [username]`
|
|
- PAT: `pass-cli login --personal-access-token <TOKEN>`
|
|
- Web: `pass-cli login`
|
|
|
|
---
|
|
|
|
#### `proton_pass_logout`
|
|
|
|
End the current Proton Pass session and clear cached credentials.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_logout",
|
|
"description": "End the current Proton Pass session.",
|
|
"parameters": {}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli logout`
|
|
|
|
---
|
|
|
|
#### `proton_pass_auth_status`
|
|
|
|
Check whether you're authenticated, with account info from `pass-cli info`.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_auth_status",
|
|
"description": "Check authentication status.",
|
|
"parameters": {}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli info`
|
|
|
|
---
|
|
|
|
#### `proton_pass_test`
|
|
|
|
Test the pass-cli connection and authentication validity.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_test",
|
|
"description": "Test connection and authentication.",
|
|
"parameters": {}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli test`
|
|
|
|
---
|
|
|
|
### Vault Tools
|
|
|
|
#### `proton_pass_vaults`
|
|
|
|
List all accessible Proton Pass vaults with share IDs and metadata.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_vaults",
|
|
"description": "List all vaults.",
|
|
"parameters": {}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli vault list --output json`
|
|
|
|
**Returns:** JSON array of vault objects with `share_id`, `name`, and metadata.
|
|
|
|
---
|
|
|
|
#### `proton_pass_vault_create`
|
|
|
|
Create a new vault.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_vault_create",
|
|
"description": "Create a new vault.",
|
|
"parameters": {
|
|
"properties": {
|
|
"name": { "type": "string", "description": "Vault name." }
|
|
},
|
|
"required": ["name"]
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli vault create --name <name>`
|
|
|
|
---
|
|
|
|
#### `proton_pass_vault_delete`
|
|
|
|
Permanently delete a vault and all its contents. **Cannot be undone.**
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_vault_delete",
|
|
"description": "Delete a vault permanently.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string", "description": "Vault share ID." },
|
|
"vault_name": { "type": "string", "description": "Vault name." }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli vault delete --share-id <id>` or `--vault-name <name>`
|
|
|
|
---
|
|
|
|
### Item Tools
|
|
|
|
#### `proton_pass_list`
|
|
|
|
List all items in a vault (names only, no secret values).
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_list",
|
|
"description": "List items in a vault.",
|
|
"parameters": {
|
|
"properties": {
|
|
"vault_name": { "type": "string", "description": "Vault name." },
|
|
"share_id": { "type": "string", "description": "Vault share ID." }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli item list [vault-name] --output json`
|
|
|
|
---
|
|
|
|
#### `proton_pass_get`
|
|
|
|
Retrieve a specific item's full details — passwords, usernames, URLs, notes, custom fields.
|
|
|
|
> **⚠️ Security:** Secrets enter the agent context. Be aware of prompt logging implications.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_get",
|
|
"description": "Get full item details.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string" },
|
|
"vault_name": { "type": "string" },
|
|
"item_id": { "type": "string" },
|
|
"item_title": { "type": "string" },
|
|
"uri": { "type": "string", "description": "pass:// URI shortcut." },
|
|
"field": { "type": "string", "description": "Specific field (password, username, etc.)." }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:**
|
|
- By ID: `pass-cli item view --share-id <sid> --item-id <iid> --output json`
|
|
- By title: `pass-cli item view --vault-name <vault> --item-title <title> --output json`
|
|
- By URI: `pass-cli item view pass://vault/item/field --output json`
|
|
|
|
---
|
|
|
|
#### `proton_pass_search`
|
|
|
|
Search items across vaults by title or name. Lists items and applies client-side filtering since pass-cli has no dedicated search subcommand.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_search",
|
|
"description": "Search items by title/name.",
|
|
"parameters": {
|
|
"properties": {
|
|
"query": { "type": "string", "description": "Search query." },
|
|
"vault_name": { "type": "string", "description": "Optional: restrict to vault." },
|
|
"share_id": { "type": "string", "description": "Optional: restrict to vault by share ID." }
|
|
},
|
|
"required": ["query"]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### `proton_pass_create`
|
|
|
|
Create a new login or note item in a vault.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_create",
|
|
"description": "Create a new item.",
|
|
"parameters": {
|
|
"properties": {
|
|
"type": { "type": "string", "enum": ["login", "note"] },
|
|
"vault_name": { "type": "string" },
|
|
"share_id": { "type": "string" },
|
|
"title": { "type": "string" },
|
|
"username": { "type": "string" },
|
|
"password": { "type": "string" },
|
|
"generate_password": { "type": "boolean" },
|
|
"url": { "type": "string" },
|
|
"note": { "type": "string" }
|
|
},
|
|
"required": ["title"]
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli item create login --title "..." --username "..." [--generate-password=...]`
|
|
|
|
---
|
|
|
|
#### `proton_pass_edit`
|
|
|
|
Update fields on an existing item.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_edit",
|
|
"description": "Update item fields.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string" },
|
|
"vault_name": { "type": "string" },
|
|
"item_id": { "type": "string" },
|
|
"item_title": { "type": "string" },
|
|
"fields": { "type": "object", "description": "Key-value map of fields to update." }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli item update --share-id <sid> --item-id <iid> --field password=newpass`
|
|
|
|
---
|
|
|
|
#### `proton_pass_delete`
|
|
|
|
Permanently delete an item.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_delete",
|
|
"description": "Delete an item.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string" },
|
|
"vault_name": { "type": "string" },
|
|
"item_id": { "type": "string" },
|
|
"item_title": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli item delete --share-id <sid> --item-id <iid>`
|
|
|
|
---
|
|
|
|
#### `proton_pass_totp`
|
|
|
|
Get the current TOTP code for an item that has two-factor authentication configured.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_totp",
|
|
"description": "Get TOTP code for an item.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string" },
|
|
"vault_name": { "type": "string" },
|
|
"item_id": { "type": "string" },
|
|
"item_title": { "type": "string" },
|
|
"uri": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli item view --share-id <sid> --item-id <iid> --field totp`
|
|
|
|
---
|
|
|
|
#### `proton_pass_share_item`
|
|
|
|
Share an item with another user.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_share_item",
|
|
"description": "Share an item with another user.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string" },
|
|
"vault_name": { "type": "string" },
|
|
"item_id": { "type": "string" },
|
|
"item_title": { "type": "string" },
|
|
"email": { "type": "string" },
|
|
"role": { "type": "string", "enum": ["viewer", "editor", "manager"] }
|
|
},
|
|
"required": ["email"]
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli item share --share-id <sid> --item-id <iid> email@example.com --role editor`
|
|
|
|
---
|
|
|
|
### Secret Injection Tools
|
|
|
|
#### `proton_pass_inject`
|
|
|
|
Run a shell command with secrets injected into environment variables. Uses `pass-cli run` which resolves `pass://` URIs in env vars before executing. Secrets are masked in stdout/stderr by default.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_inject",
|
|
"description": "Run command with secret-injected env vars.",
|
|
"parameters": {
|
|
"properties": {
|
|
"command": { "type": "string", "description": "Command to execute." },
|
|
"env_files": { "type": "array", "items": {"type": "string"}, "description": ".env files to load." },
|
|
"no_masking": { "type": "boolean", "description": "Disable secret masking." }
|
|
},
|
|
"required": ["command"]
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli run --env-file .env -- ./my-app`
|
|
|
|
**Example usage:**
|
|
```bash
|
|
export DB_PASSWORD='pass://Production/Database/password'
|
|
pass-cli run -- ./my-app
|
|
```
|
|
|
|
---
|
|
|
|
### SSH Agent Tools
|
|
|
|
#### `proton_pass_ssh_load`
|
|
|
|
Load SSH keys from Proton Pass into the system's SSH agent. Requires `SSH_AUTH_SOCK` to be set.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_ssh_load",
|
|
"description": "Load SSH keys from Proton Pass.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string", "description": "Restrict to a vault." },
|
|
"vault_name": { "type": "string", "description": "Restrict to a vault." }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli ssh-agent load [--share-id <sid>]`
|
|
|
|
---
|
|
|
|
#### `proton_pass_ssh_agent_start`
|
|
|
|
Start Proton Pass CLI as the SSH agent (foreground). Sets `SSH_AUTH_SOCK` to the agent's Unix socket.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_ssh_agent_start",
|
|
"description": "Start Proton Pass as SSH agent.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string" },
|
|
"vault_name": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli ssh-agent start`
|
|
|
|
---
|
|
|
|
#### `proton_pass_ssh_daemon_start` / `_status` / `_stop`
|
|
|
|
Start, check, or stop the Proton Pass SSH agent background daemon.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_ssh_daemon_start",
|
|
"description": "Start SSH daemon.",
|
|
"parameters": {
|
|
"properties": {
|
|
"share_id": { "type": "string" },
|
|
"vault_name": { "type": "string" },
|
|
"log_file": { "type": "string", "description": "Log file path." }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli ssh-agent daemon start|status|stop`
|
|
|
|
---
|
|
|
|
### Utility Tools
|
|
|
|
#### `proton_pass_generate_password`
|
|
|
|
Generate a random password or passphrase and optionally save it to a vault.
|
|
|
|
```json
|
|
{
|
|
"name": "proton_pass_generate_password",
|
|
"description": "Generate password or passphrase.",
|
|
"parameters": {
|
|
"properties": {
|
|
"length": { "type": "integer", "description": "Password length (default: 20)." },
|
|
"passphrase": { "type": "boolean", "description": "Generate passphrase." },
|
|
"word_count": { "type": "integer", "description": "Passphrase word count (default: 4)." },
|
|
"save": { "type": "boolean", "description": "Save to vault." },
|
|
"vault_name": { "type": "string" },
|
|
"title": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**CLI mapping:** `pass-cli item create login --title "..." --generate-password=20,uppercase,symbols`
|
|
|
|
---
|
|
|
|
## Implementation
|
|
|
|
All tools shell out to `pass-cli` via Python `subprocess`. The implementation module lives at `scripts/tools.py` in this skill directory.
|
|
|
|
### General Pattern
|
|
|
|
```python
|
|
import subprocess
|
|
import json
|
|
import shlex
|
|
|
|
def _run_pass(args: list[str], timeout: int = 15) -> dict:
|
|
"""Run a pass-cli command and return structured output."""
|
|
try:
|
|
result = subprocess.run(
|
|
[binary] + args,
|
|
capture_output=True, text=True, timeout=timeout
|
|
)
|
|
if result.returncode != 0:
|
|
return {"success": False, "error": result.stderr.strip()}
|
|
# Auto-parse JSON output
|
|
try:
|
|
data = json.loads(result.stdout)
|
|
return {"success": True, "data": data}
|
|
except json.JSONDecodeError:
|
|
return {"success": True, "output": result.stdout.strip()}
|
|
except subprocess.TimeoutExpired:
|
|
return {"success": False, "error": f"Command timed out after {timeout}s"}
|
|
except FileNotFoundError:
|
|
return {"success": False, "error": "pass-cli not found. Install via official installer."}
|
|
```
|
|
|
|
### Output Format
|
|
|
|
pass-cli supports `--output json` on most commands, making parsing straightforward. The tools auto-detect JSON output and return structured data directly. When the CLI returns non-JSON (e.g., login prompts, info output), the raw text is returned in an `output` field.
|
|
|
|
### Binary Path
|
|
|
|
The pass-cli binary location can be configured via:
|
|
- Environment variable: `PROTON_PASS_CLI_PATH` (e.g., `/usr/local/bin/pass-cli`)
|
|
- Default: `pass-cli` (searched via `PATH`)
|
|
|
|
## Dependencies
|
|
|
|
| Dependency | Required | Notes |
|
|
|------------|----------|-------|
|
|
| `pass-cli` (>= 2.1.0) | Yes | Official Proton Pass Rust CLI. [GitHub](https://github.com/ProtonPass/pass-cli) |
|
|
| `ssh-agent` | Optional | Required for SSH key load functionality. Present on most systems. |
|
|
| `openssh-client` | Optional | For SSH operations. |
|
|
|
|
## Security
|
|
|
|
### Secret Context Exposure
|
|
|
|
**This is the most important consideration for this skill.** Passwords and secrets returned by `pass-cli` enter the agent's context directly. This is expected (the agent needs secrets to use them), but has implications:
|
|
|
|
- **Prompt logging** — Secrets may appear in chat history or session logs
|
|
- **`proton_pass_inject`** — Sets temporary env vars for subprocesses with automatic masking of secrets in stdout/stderr
|
|
- **`proton_pass_get`** — Returns full item details including passwords. Use only when the agent genuinely needs the value
|
|
- **Client-side filtering** — `proton_pass_search` retrieves item names only, not secret values
|
|
|
|
### Session Security
|
|
|
|
- pass-cli stores session data encrypted in the platform-specific secure location
|
|
- Session persists until explicit logout (`proton_pass_logout`)
|
|
- Personal Access Tokens provide scoped, revocable access — recommended over full credential login for automation
|
|
- SSH keys stored in Proton Pass are encrypted at rest within the vault
|
|
|
|
### Best Practices
|
|
|
|
1. **Use PAT for automation** — Avoid interactive password/PIN entry in CI/CD
|
|
2. **Minimize `get` calls** — Retrieve only the secrets you need, not entire items
|
|
3. **Prefer `inject`** — Use `proton_pass_inject` to pass secrets as env vars to subprocesses rather than reading them into agent context
|
|
4. **Log out after batch operations** — `proton_pass_logout` when done with a session
|
|
5. **Environment variables** — Set `PROTON_PASS_CLI_PATH` if `pass-cli` isn't in `PATH`
|
|
|
|
## Limitations
|
|
|
|
1. **pass-cli must be installed separately** — Not bundled with Hermes
|
|
2. **Secrets in agent context** — Use `inject` mode to minimize exposure
|
|
3. **Interactive login needs TTY** — Browser or credential prompts require user interaction
|
|
4. **SSH agent requires `SSH_AUTH_SOCK`** — Only works when an SSH agent is running
|
|
5. **No native search** — pass-cli's `item view` supports lookup by title, but full text search is implemented client-side via listing + filtering
|
|
6. **TOTP field access** — Uses the `totp` field on items via `item view --field totp`; works only if TOTP is configured for that item
|
|
|
|
## Related
|
|
|
|
- [Proton Pass CLI Documentation](https://protonpass.github.io/pass-cli/)
|
|
- [Proton Pass CLI GitHub](https://github.com/ProtonPass/pass-cli)
|
|
- [Secret References Syntax](https://protonpass.github.io/pass-cli/commands/contents/secret-references/)
|
|
- [ARCHITECTURE.md](../../ARCHITECTURE.md) — Hermes-Proton integration design (section 4)
|