[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-82243":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":13,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":13,"stars7d":15,"stars30d":15,"stars90d":13,"forks30d":13,"starsTrendScore":13,"compositeScore":16,"rankGlobal":10,"rankLanguage":10,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":20,"topics":21,"createdAt":10,"pushedAt":10,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":13,"starSnapshotCount":13,"syncStatus":15,"lastSyncTime":25,"discoverSource":26},82243,"keyledger","riptideslabs\u002Fkeyledger","riptideslabs","Unified TUI for inventory, health-check, and track every API key issued across your AI providers.","https:\u002F\u002Fkeyledger.riptides.io\u002F",null,"Go",24,0,21,2,41.2,"MIT License",false,"main",true,[],"2026-06-12 04:01:37","# KeyLedger\n\nKeyLedger is an interactive terminal dashboard that gives you a unified view of every API key issued across your AI providers — with health scoring, snapshot diffs, and encrypted credential storage.\n\n![Demo](docs\u002Fdemos\u002Fdemo.gif)\n\n## Features\n\n- **Interactive TUI** — full-screen terminal dashboard built with [Bubble Tea](https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Fbubbletea)\n- **Unified inventory** — query all your AI providers simultaneously with a configurable timeout\n- **Health scoring** — flag stale, idle, or never-used keys with configurable age thresholds; dedicated Risk column sortable in the keys view\n- **WorkSpaces view** — hierarchical workspace\u002Fproject tree per provider with per-scope key counts and risk breakdown, accessible as a tab inside the Keys view\n- **Live filtering** — search keys by name, scope, status, age, owner, risk score, and more\n- **Snapshots manager** — list, export, delete, and diff snapshots from a dedicated Snapshots view; trigger snapshots from the Keys or Health views\n- **Periodic watch mode** — collect keys on a schedule, persist to database, and dump JSON files automatically\n- **Encrypted credential storage** — credentials stored in AES-256-GCM encrypted SQLite; never plaintext on disk\n- **Provider management UI** — enable\u002Fdisable providers and configure credentials interactively; credential status shown as \"set\" or \"missing\"\n\n## Documentation\n\nProvider setup guides, configuration reference, and examples are at [keyledger.riptides.io](https:\u002F\u002Fkeyledger.riptides.io\u002F).\n\n## Provider Coverage\n\n| Provider | Key listing | Owner info | Last used |\n|---|---|---|---|\n| OpenAI | ✓ | ✓ | ✓ |\n| Anthropic | ✓ | ✓ | ✓ (30-day window) |\n| AWS IAM access keys | ✓ | ✓ | ✓ |\n| AWS service-specific credentials | ✓ | ✓ | — |\n| Google Cloud IAM | ✓ | — | — |\n| Mistral | ✓ | ✓ | ✓ |\n\n## Installation\n\n### go install\n\n```bash\ngo install github.com\u002Friptideslabs\u002Fkeyledger@latest\n```\n\n### Build from source\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Friptideslabs\u002Fkeyledger\ncd keyledger\nmake build\n.\u002Fbuild\u002Fkeyledger\n```\n\n### Install to GOPATH\u002Fbin\n\n```bash\nmake install\n```\n\nRequires Go 1.25 or later. No CGO required.\n\n## Configuration\n\n### Credentials\n\nLaunch the TUI and press **`p`** to open the Providers screen. Select a provider, enable it, and enter your API credentials — they are stored in an AES-256-GCM encrypted SQLite database and never written to disk in plaintext. You will be prompted to set a master password on first use.\n\n### OpenAI\n\n| Credential field | Description |\n|---|---|\n| `admin_key` | An Admin API key (`sk-admin-…`) from platform.openai.com → API keys |\n\nThe admin key must have permission to list keys across the organisation. By default all projects are enumerated; use **Exclude projects** in the Providers screen to skip specific ones.\n\n### Anthropic\n\n| Credential field | Description |\n|---|---|\n| `admin_key` | An Admin API key (`sk-ant-admin01-…`) from console.anthropic.com → API Keys |\n\nThe admin key must belong to an account with the **Admin** role. Optional settings (resolve user\u002Fworkspace names, exclude workspaces) are configurable from the Providers screen.\n\n### AWS\n\nThree credential modes are supported, tried in this order:\n\n| Mode | Credential field | Description |\n|---|---|---|\n| SSO profile | `sso_creds` | Profile name from `~\u002F.aws\u002Fconfig` after `aws sso login` |\n| Static keys | `access_key_id` + `secret_access_key` | Long-lived IAM access keys |\n\nEither `sso_creds` alone, or both `access_key_id` **and** `secret_access_key`, must be set — the Providers screen shows **set** when the minimum required fields are present.\n\n### Google Cloud\n\n| Credential field | Description |\n|---|---|\n| `service_account_json` | Full JSON content of a GCP service account key file |\n\nPaste the entire contents of the downloaded `.json` key file into the `service_account_json` field. The service account needs the following roles (or equivalent custom permissions):\n\n- `roles\u002Fresourcemanager.projectViewer` — to enumerate projects\n- `roles\u002Fapikeys.viewer` — to list API keys\n- `roles\u002Fiam.serviceAccountViewer` — to list service account keys\n\nBy default all accessible projects are auto-discovered. Use **Projects (override)** to pin a list of project IDs, or **Exclude projects** to skip specific ones.\n\n### Mistral\n\nMistral uses an interactive login flow rather than a static API key. In the Providers screen press **Login** and enter your Mistral email and password — keyledger authenticates via Mistral's Kratos endpoint and stores the session token automatically. The session token is refreshed on each login.\n\n## Usage\n\n### Interactive TUI\n\n```bash\nkeyledger\n```\n\nLaunches the full-screen dashboard. All state (enabled providers, settings, snapshots) is persisted to `~\u002F.keyledger\u002Fkeyledger.db`.\n\n### Keyboard shortcuts\n\n| Key | Action |\n|---|---|\n| `1` | Keys view |\n| `2` | Health view |\n| `3` | Diff view |\n| `4` | Snapshots view |\n| `p` | Provider management |\n| `g` | Settings |\n| `r` | Refresh all providers |\n| `s` | Save snapshot to database (Keys \u002F Health views) |\n| `tab` | Toggle sidebar focus |\n| `o` | Cycle sort order (Keys view) |\n| `← →` | Switch between Keys and WorkSpaces tabs (Keys view) |\n| `\u002F` | Filter keys (Keys view) |\n| `?` | Toggle help overlay |\n| `esc` | Go back \u002F close dialog |\n| `q` | Quit |\n\n#### Keys view columns\n\nThe keys table includes a dedicated **Risk** column (`ok` \u002F `WARN` \u002F `CRIT`) alongside the status column, so you can see health at a glance without opening the Health view. The active sort column is highlighted in purple with an underline. Sort cycles through: Created → Last Used → Name → Risk.\n\n#### Keys view filter syntax\n\n| Expression | Matches |\n|---|---|\n| `foo` | Substring in ID, name, scope, or status |\n| `name:prod` | Keys whose name contains \"prod\" |\n| `scope:staging` | Keys in a scope containing \"staging\" |\n| `status:active` | Keys with exact status \"active\" |\n| `risk:critical` | Keys with risk score \"critical\" |\n| `age:>90` | Keys older than 90 days |\n| `idle:never` | Keys that have never been used |\n| `owner:alice` | Keys created by a user matching \"alice\" |\n\n### Watch mode\n\n```bash\nkeyledger watch [--interval \u003Cduration>] [--output \u003Cdir>] [--unseal-addr \u003Caddr>]\nkeyledger --data-dir \u002Fmnt\u002Fdata watch --interval 1h\n```\n\nRuns continuously: collects keys, saves to the database, and dumps a JSON file on every tick. Stops cleanly on `Ctrl+C` or `SIGTERM`.\n\n```bash\nkeyledger watch --interval 1h --output \u002Fvar\u002Flog\u002Fkeyledger\n```\n\nEach run prints a one-line summary:\n\n```\n[2026-05-11 03:00:00] snapshot #12 — 47 keys (0 critical, 2 warnings) → \u002Fvar\u002Flog\u002Fkeyledger\u002Fsnapshot-20260511T030000.json\n```\n\nThe `--interval` flag accepts any Go duration string: `30m`, `1h`, `6h`, `24h`, etc. Default is `1h`.\n\n`--output` sets where snapshot JSON files are written. The database lives separately — use `--data-dir` (or `$KEYLEDGER_HOME`) to point it elsewhere; the startup line `watch: store: …` always shows which database is active.\n\n#### Unseal API (headless \u002F Docker)\n\nIn headless environments (e.g. a Linux container without a terminal), `watch` automatically starts a local HTTPS API so credentials can be supplied at runtime.\n\n```\nwatch: credential store locked — POST password to https:\u002F\u002F127.0.0.1:9876\u002Fv1\u002Funseal\nwatch: TLS cert fingerprint (SHA-256): AB:CD:EF:…\n```\n\nThe server uses an ephemeral self-signed TLS certificate (ECDSA P-256, valid 24 h). Use `--unseal-addr` to change the bind address (default `127.0.0.1:9876`).\n\n| Endpoint | Method | Body | Description |\n|---|---|---|---|\n| `\u002Fv1\u002Fstatus` | GET | — | `{\"sealed\":bool,\"setup\":bool}` |\n| `\u002Fv1\u002Fproviders` | GET | — | List registered providers and their expected field names |\n| `\u002Fv1\u002Finit` | POST | `{\"password\":\"…\"}` | Initialise encryption on first run, then unseal |\n| `\u002Fv1\u002Funseal` | POST | `{\"password\":\"…\"}` | Unseal an already-initialised store |\n| `\u002Fv1\u002Fcredentials` | POST | `{\"provider\":\"…\",\"field\":\"…\",\"value\":\"…\"}` | Store a credential and enable the provider (requires unsealed) |\n| `\u002Fv1\u002Fcredentials` | DELETE | `{\"provider\":\"…\",\"field\":\"…\"}` | Remove a credential (requires unsealed) |\n\nUse `GET \u002Fv1\u002Fproviders` to discover the exact field names before posting credentials:\n\n```bash\ncurl -sk https:\u002F\u002Flocalhost:9876\u002Fv1\u002Fproviders\n# [\n#   {\"provider\":\"anthropic\",\"fields\":[\"admin_key\"]},\n#   {\"provider\":\"aws\",\"fields\":[\"access_key_id\",\"secret_access_key\",\"sso_creds\"]},\n#   {\"provider\":\"google\",\"fields\":[\"service_account_json\"]},\n#   {\"provider\":\"openai\",\"fields\":[\"admin_key\"]}\n# ]\n```\n\n### Docker\n\nPre-built multi-arch images (linux\u002Famd64, linux\u002Farm64) are published to the GitHub Container Registry on every release:\n\n```bash\ndocker pull ghcr.io\u002Friptideslabs\u002Fkeyledger:latest\ndocker run -p 9876:9876 -v keyledger-data:\u002Fdata ghcr.io\u002Friptideslabs\u002Fkeyledger:latest\n```\n\nOr build locally from source:\n\n```bash\ndocker build -t keyledger .\ndocker run -p 9876:9876 -v keyledger-data:\u002Fdata keyledger\n```\n\nThe container runs `keyledger watch --unseal-addr 0.0.0.0:9876 --interval 5m` by default. Use the unseal API to supply credentials:\n\n```bash\n# 1. Check whether encryption has been initialised yet\ncurl -sk https:\u002F\u002Flocalhost:9876\u002Fv1\u002Fstatus\n# {\"sealed\":true,\"setup\":false}\n\n# 2a. First run — initialise encryption and unseal in one step\ncurl -sk -X POST https:\u002F\u002Flocalhost:9876\u002Fv1\u002Finit \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"password\":\"my-secret\"}'\n# {\"sealed\":false}\n\n# 2b. Subsequent restarts — store is already initialised, just unseal\ncurl -sk -X POST https:\u002F\u002Flocalhost:9876\u002Fv1\u002Funseal \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"password\":\"my-secret\"}'\n\n# 3. Push provider credentials\ncurl -sk -X POST https:\u002F\u002Flocalhost:9876\u002Fv1\u002Fcredentials \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"provider\":\"openai\",\"field\":\"admin_key\",\"value\":\"sk-...\"}'\n\ncurl -sk -X POST https:\u002F\u002Flocalhost:9876\u002Fv1\u002Fcredentials \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"provider\":\"anthropic\",\"field\":\"admin_key\",\"value\":\"sk-ant-...\"}'\n\n# Remove a credential\ncurl -sk -X DELETE https:\u002F\u002Flocalhost:9876\u002Fv1\u002Fcredentials \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"provider\":\"openai\",\"field\":\"admin_key\"}'\n```\n\n> **Note:** `-sk` skips certificate verification for the self-signed cert. For stricter usage, extract the SHA-256 fingerprint printed at startup and pass it to `curl --pinnedpubkey sha256\u002F\u002F\u003Cbase64>` or verify with `openssl s_client -connect localhost:9876`.\n\n## Development\n\n```bash\nmake help        # list all targets\nmake build       # build for current platform\nmake build-all   # cross-compile for all platforms\nmake run         # build and launch the TUI\nmake test        # run tests with coverage\nmake lint        # run golangci-lint (downloads on first run)\nmake lint-fix    # run golangci-lint with auto-fix\nmake check       # fmt + vet + lint\nmake clean       # remove build artifacts\n```\n\n## License\n\nMIT — see [LICENSE](LICENSE). Copyright © 2026 Riptides Labs, Inc.\n","KeyLedger 是一个统一的终端用户界面，用于管理、健康检查和跟踪跨多个AI提供商发放的所有API密钥。它采用Go语言编写，通过Bubble Tea框架构建了一个全屏的交互式终端仪表盘，支持实时过滤、快照管理和周期性监控模式等功能。此外，KeyLedger还提供了加密凭证存储以确保安全。该项目特别适合需要对多个AI服务提供商的API密钥进行集中管理和监控的企业或团队使用，能够帮助识别过期或未使用的密钥，并评估整体风险状况。","2026-06-11 04:08:09","CREATED_QUERY"]