{"id":50515341,"url":"https://github.com/dkmaker/apikeymanager","last_synced_at":"2026-06-02T23:31:06.373Z","repository":{"id":345332164,"uuid":"1185495730","full_name":"dkmaker/apikeymanager","owner":"dkmaker","description":"GNOME tray app that syncs 1Password API keys to local shell sessions — in-memory, lock-aware","archived":false,"fork":false,"pushed_at":"2026-03-27T10:05:01.000Z","size":180,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T21:58:52.815Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dkmaker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-18T16:36:59.000Z","updated_at":"2026-03-27T10:04:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dkmaker/apikeymanager","commit_stats":null,"previous_names":["dkmaker/apikeymanager"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dkmaker/apikeymanager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkmaker%2Fapikeymanager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkmaker%2Fapikeymanager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkmaker%2Fapikeymanager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkmaker%2Fapikeymanager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dkmaker","download_url":"https://codeload.github.com/dkmaker/apikeymanager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkmaker%2Fapikeymanager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33841995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-02T23:31:05.580Z","updated_at":"2026-06-02T23:31:06.367Z","avatar_url":"https://github.com/dkmaker.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# op-keysync\n\nA GNOME tray app that fetches API keys from 1Password and injects them as environment variables into your local shell sessions — with automatic purge on screen lock and idle timeout.\n\n## Install\n\n```bash\n# 1. Add the GPG key\ncurl -fsSL https://dkmaker.github.io/apikeymanager/gpg.key \\\n  | sudo gpg --dearmor -o /usr/share/keyrings/op-keysync.gpg\n\n# 2. Add the repository\necho \"deb [arch=all signed-by=/usr/share/keyrings/op-keysync.gpg] \\\n  https://dkmaker.github.io/apikeymanager stable main\" \\\n  | sudo tee /etc/apt/sources.list.d/op-keysync.list\n\n# 3. Install\nsudo apt update \u0026\u0026 sudo apt install op-keysync\n```\n\nThen launch **1Password Key Sync** from your GNOME app menu.\n\n\u003e Full installation details, requirements, and 1Password vault setup: see [INSTALL.md](INSTALL.md)\n\n## How it works\n\n- **Secrets live only in RAM** — encrypted with Fernet (AES-128-CBC), key generated fresh at startup, never written to disk\n- **On startup** — auto-syncs from 1Password after 2 seconds\n- **On screen lock** — secrets purged from memory → all local shells unset vars on next prompt\n- **On 60 min idle** — same purge, triggered by no keyboard/mouse input via Mutter idle monitor\n- **On unlock / activity resumes** — 1Password queried automatically, fresh keys loaded → shells re-inject\n- **Manual sync** — \"Full Sync\" in tray menu fetches from 1Password on demand\n- **Clipboard** — copy value or `KEY=VALUE` from tray submenu, auto-cleared after 20 seconds\n- **SSH sessions denied** — shell hook checks `$SSH_CONNECTION` and skips entirely\n\n## Security model\n\n| Concern | How it's handled |\n|---|---|\n| Keys on disk | Never written — `/run/user/$UID/` is tmpfs (RAM only) |\n| Keys in keyring | Not used — no `secret-tool`, no GNOME keyring |\n| SSH access | Shell hook checks `$SSH_CONNECTION` and skips entirely |\n| Screen lock | D-Bus `org.gnome.ScreenSaver.ActiveChanged` triggers immediate purge |\n| Idle timeout | D-Bus `org.gnome.Mutter.IdleMonitor` purges after 60 min no input |\n| Socket access | Socket is `chmod 600`, owner-only |\n| Key values in menu | Never shown in header — values only accessible via submenu |\n| Clipboard | Values passed via `wl-copy` stdin (never in process args), auto-cleared after 20s |\n\n## Tray icon\n\n| Colour | Meaning |\n|---|---|\n| 🟢 Green | Unlocked, keys loaded |\n| 🔴 Red | Screen locked, keys purged |\n| 🟠 Orange | Sync error |\n| 🔵 Blue | Currently syncing |\n| 🟡 Amber | Secret copied to clipboard, waiting 20s auto-clear |\n| ⚪ Grey | Running, no keys yet |\n\n## Architecture\n\n```mermaid\ngraph TD\n    OP[1Password CLI\u003cbr/\u003e\u003ccode\u003eop\u003c/code\u003e] --\u003e|fetch vault items| SYNC\n\n    subgraph App[\"op-keysync — GNOME tray app\"]\n        SYNC[Sync engine] --\u003e|encrypt with Fernet| MEM[(In-memory\u003cbr/\u003eencrypted secrets)]\n        MEM --\u003e SOCK[Unix socket server\u003cbr/\u003e\u003ccode\u003e/run/user/UID/op-keysync/sock\u003c/code\u003e]\n        DBUS[D-Bus listener\u003cbr/\u003eScreenSaver + Mutter IdleMonitor] --\u003e|lock / idle| PURGE[Purge secrets\u003cbr/\u003ebump version]\n        DBUS --\u003e|unlock / resume| SYNC\n        PURGE --\u003e MEM\n    end\n\n    SOCK --\u003e|export KEY=value| HOOK\n    RUNDIR[(\"\u003ccode\u003e/run/user/UID/op-keysync/\u003c/code\u003e\u003cbr/\u003estate · version\")] --\u003e|version changed?| HOOK\n\n    subgraph Shell[\"Shell hook  (bash / zsh)\"]\n        HOOK[precmd / PROMPT_COMMAND\u003cbr/\u003echecks version file on every prompt]\n        HOOK --\u003e|locked| UNSET[unset tracked vars]\n        HOOK --\u003e|unlocked + new version| SOCAT[socat → socket\u003cbr/\u003eexport vars into shell]\n    end\n\n    SSH{{SSH session?}} --\u003e|yes — skip entirely| HOOK\n```\n\n## Troubleshooting\n\n```bash\n# Check daemon is running\nls /run/user/$UID/op-keysync/\n\n# Check state\ncat /run/user/$UID/op-keysync/state\n\n# Test socket manually\nprintf 'GET\\n' | socat -t2 - UNIX-CONNECT:/run/user/$UID/op-keysync/sock\n\n# Debug log\ntail -f ~/.local/share/op-keysync/debug.log\n\n# Test 1Password CLI\nop item list --vault Exports --format json\n```\n\n## Known limitations\n\n- **Clipboard clear-on-paste** — not possible on GNOME Wayland (Mutter doesn't support `wlr-data-control`). Uses 20-second auto-clear instead, same as 1Password, KeePassXC and Bitwarden.\n- **GTK3** — required because `AyatanaAppIndicator` (system tray) has no GTK4 support.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkmaker%2Fapikeymanager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdkmaker%2Fapikeymanager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkmaker%2Fapikeymanager/lists"}