Phase 3: proton-pass skill — 22 tool handlers wrapping pass-cli (vaults, items, TOTP, SSH, inject)
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
This commit is contained in:
parent
f8b9991207
commit
27592f710b
4 changed files with 2178 additions and 0 deletions
621
skills/proton-pass/SKILL.md
Normal file
621
skills/proton-pass/SKILL.md
Normal file
|
|
@ -0,0 +1,621 @@
|
||||||
|
---
|
||||||
|
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)
|
||||||
107
skills/proton-pass/references/commands.md
Normal file
107
skills/proton-pass/references/commands.md
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
# Proton Pass CLI Command Reference
|
||||||
|
|
||||||
|
> Reference: https://protonpass.github.io/pass-cli/
|
||||||
|
|
||||||
|
## Auth Commands
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `pass-cli login [--interactive [USERNAME]]` | Interactive login (password, TOTP, extra pwd) |
|
||||||
|
| `pass-cli login --personal-access-token <TOKEN>` | PAT-based login for automation |
|
||||||
|
| `pass-cli login` | Web browser OAuth login |
|
||||||
|
| `pass-cli logout` | End current session |
|
||||||
|
| `pass-cli info` | Show account/session info |
|
||||||
|
| `pass-cli test` | Test connection & auth |
|
||||||
|
|
||||||
|
## Vault Commands
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `pass-cli vault list [--output json]` | List all vaults |
|
||||||
|
| `pass-cli vault create --name NAME` | Create vault |
|
||||||
|
| `pass-cli vault update --share-id SID --name NEW_NAME` | Rename vault |
|
||||||
|
| `pass-cli vault delete --share-id SID` | Delete vault (permanent) |
|
||||||
|
| `pass-cli vault share SID EMAIL [--role ROLE]` | Share vault |
|
||||||
|
| `pass-cli vault transfer SID MEMBER_SID` | Transfer ownership |
|
||||||
|
| `pass-cli vault member list --share-id SID` | List members |
|
||||||
|
|
||||||
|
## Item Commands
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `pass-cli item list [VAULT] [--output json]` | List items |
|
||||||
|
| `pass-cli item create login [OPTIONS]` | Create login item |
|
||||||
|
| `pass-cli item create note [OPTIONS]` | Create note item |
|
||||||
|
| `pass-cli item create ssh-key generate [OPTIONS]` | Generate SSH key |
|
||||||
|
| `pass-cli item create ssh-key import --from-private-key PATH` | Import SSH key |
|
||||||
|
| `pass-cli item view --share-id SID --item-id IID [--output json]` | View item |
|
||||||
|
| `pass-cli item view pass://SID/IID/FIELD [--output json]` | View by URI |
|
||||||
|
| `pass-cli item update --share-id SID --item-id IID --field K=V` | Update fields |
|
||||||
|
| `pass-cli item delete --share-id SID --item-id IID` | Delete item |
|
||||||
|
| `pass-cli item share --share-id SID --item-id IID EMAIL --role ROLE` | Share item |
|
||||||
|
| `pass-cli item attachment download [OPTIONS]` | Download attachment |
|
||||||
|
| `pass-cli item alias create [OPTIONS]` | Create alias |
|
||||||
|
|
||||||
|
## View Item Contents
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `pass-cli view pass://VAULT/ITEM/FIELD` | View/resolve a secret reference |
|
||||||
|
| `pass-cli run [--env-file FILE] -- COMMAND` | Run command with injected secrets |
|
||||||
|
| `pass-cli inject [--in-file FILE] [--out-file FILE]` | Process template with secrets |
|
||||||
|
|
||||||
|
## TOTP
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `pass-cli item view --share-id SID --item-id IID --field totp` | Get TOTP code |
|
||||||
|
|
||||||
|
## SSH Agent
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `pass-cli ssh-agent load` | Load keys into system SSH agent |
|
||||||
|
| `pass-cli ssh-agent start` | Start as SSH agent (foreground) |
|
||||||
|
| `pass-cli ssh-agent daemon start` | Start SSH daemon (background) |
|
||||||
|
| `pass-cli ssh-agent daemon status` | Check daemon status |
|
||||||
|
| `pass-cli ssh-agent daemon stop` | Stop daemon |
|
||||||
|
|
||||||
|
## Settings & Other
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `pass-cli settings [--default-vault NAME] [--default-format FORMAT]` | Configure defaults |
|
||||||
|
| `pass-cli password generate [LENGTH]` | Generate password |
|
||||||
|
| `pass-cli password passphrase [WORD_COUNT]` | Generate passphrase |
|
||||||
|
| `pass-cli share --vault-name VAULT EMAIL [--role ROLE]` | Share vault/items |
|
||||||
|
| `pass-cli pat create [OPTIONS]` | Create personal access token |
|
||||||
|
| `pass-cli pat revoke <PAT_ID>` | Revoke a PAT |
|
||||||
|
| `pass-cli update` | Self-update pass-cli binary |
|
||||||
|
| `pass-cli user info` | Detailed user info |
|
||||||
|
| `pass-cli agent` | Agent management |
|
||||||
|
|
||||||
|
## Secret Reference Syntax
|
||||||
|
|
||||||
|
```
|
||||||
|
pass://<vault-identifier>/<item-identifier>/<field-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
- vault-identifier: Share ID or vault name
|
||||||
|
- item-identifier: Item ID or title
|
||||||
|
- field-name: case-sensitive field name (password, username, email, url, note, totp, custom)
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
| Variable | Purpose |
|
||||||
|
|----------|---------|
|
||||||
|
| `PROTON_PASS_PASSWORD` | Interactive login password |
|
||||||
|
| `PROTON_PASS_PASSWORD_FILE` | Path to password file |
|
||||||
|
| `PROTON_PASS_TOTP` | TOTP code for login |
|
||||||
|
| `PROTON_PASS_TOTP_FILE` | Path to TOTP file |
|
||||||
|
| `PROTON_PASS_EXTRA_PASSWORD` | Extra password |
|
||||||
|
| `PROTON_PASS_EXTRA_PASSWORD_FILE` | Path to extra password file |
|
||||||
|
| `PROTON_PASS_PERSONAL_ACCESS_TOKEN` | PAT for automation login |
|
||||||
|
| `PROTON_PASS_SSH_KEY_PASSWORD` | SSH key passphrase |
|
||||||
|
| `PROTON_PASS_SSH_KEY_PASSWORD_FILE` | Path to SSH key passphrase file |
|
||||||
|
| `PROTON_PASS_SSH_DAEMON_PIDFILE` | Custom PID file path |
|
||||||
|
| `PROTON_PASS_CLI_PATH` | Custom binary path (used by the Hermes skill) |
|
||||||
1427
skills/proton-pass/scripts/tools.py
Normal file
1427
skills/proton-pass/scripts/tools.py
Normal file
File diff suppressed because it is too large
Load diff
23
skills/proton-pass/scripts/verify.py
Normal file
23
skills/proton-pass/scripts/verify.py
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Verify proton-pass skill module loads and all tools are registered."""
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, 'skills/proton-pass/scripts')
|
||||||
|
|
||||||
|
import tools
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Verify all tools are in registry
|
||||||
|
print("=== Tool Registry ===")
|
||||||
|
for name, info in sorted(tools.TOOLS.items()):
|
||||||
|
params = info["schema"].get("parameters", {}).get("properties", {})
|
||||||
|
print(f" \u2713 {name} \u2014 {len(params)} params")
|
||||||
|
|
||||||
|
print(f"\nTotal tools: {len(tools.TOOLS)}")
|
||||||
|
|
||||||
|
# Test dispatch for error cases (no CLI installed = expected)
|
||||||
|
result = json.loads(tools.dispatch('proton_pass_auth_status'))
|
||||||
|
print(f"\nAuth status dispatch (expected error \u2014 no CLI): success={result.get('success')}")
|
||||||
|
print(f" error={str(result.get('error', result.get('message', '')))[:120]}")
|
||||||
|
|
||||||
|
result2 = json.loads(tools.dispatch('nonexistent'))
|
||||||
|
print(f"\nNonexistent tool: error={result2.get('error', '')[:80]}")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue