{"_id":"21pins","name":"21pins","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.1":{"name":"21pins","version":"0.1.1","description":"Local-first LLM key manager and localhost gateway for safer AI apps and agents.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/automatethething/21pins.git"},"homepage":"https://21pins.com","bugs":{"url":"https://github.com/automatethething/21pins/issues"},"bin":{"21pins":"bin/21pins.js"},"scripts":{"test":"node --test test/*.test.js","check:tag":"node scripts/check-version-tag.js","check:platforms":"node scripts/check-platform-packages.js","prepare:platforms":"node scripts/prepare-platform-packages.js","pack:platforms":"node scripts/pack-platform-packages.js"},"optionalDependencies":{"@privacyguy/21pins-darwin-arm64":"0.1.1","@privacyguy/21pins-darwin-x64":"0.1.1","@privacyguy/21pins-linux-arm64":"0.1.1","@privacyguy/21pins-linux-x64":"0.1.1"},"engines":{"node":">=18"},"os":["darwin","linux"],"cpu":["x64","arm64"],"private":false,"gitHead":"29daab1506002d7431ad67db9991aa46b22dbace","_id":"21pins@0.1.1","_nodeVersion":"24.14.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-Sg1QexliKcMOw5Ypt0uzw7PnSq4yvI2VuVYIUbj90EQ8whp29HE5MAv2/HyLmZnn3r/uLKQC9N9fQcyA5p1S+g==","shasum":"15acc876ec7d611c377af1f4186319a4a5445fba","tarball":"https://registry.npmjs.org/21pins/-/21pins-0.1.1.tgz","fileCount":9,"unpackedSize":11461,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCubO4CVlj9LrLf4X48Lu9aPAKiT2uUp3Ob19AAnSsmMgIhAPGLQ3uq9gU/pMf1+ua6ZAke8VImj/9GJnaYKn2elybF"}]},"_npmUser":{"name":"privacyguy","email":"kris@privasectech.com"},"directories":{},"maintainers":[{"name":"privacyguy","email":"kris@privasectech.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/21pins_0.1.1_1788505312519_0.8843702528448549"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-04T07:01:52.455Z","0.1.1":"2026-09-04T07:01:52.654Z","modified":"2026-09-04T07:01:52.914Z"},"maintainers":[{"name":"privacyguy","email":"kris@privasectech.com"}],"description":"Local-first LLM key manager and localhost gateway for safer AI apps and agents.","homepage":"https://21pins.com","repository":{"type":"git","url":"git+https://github.com/automatethething/21pins.git"},"bugs":{"url":"https://github.com/automatethething/21pins/issues"},"license":"MIT","readme":"# 21pins\n\n**Never accidentally share your LLM API keys again.**\n\n21pins is a local-first CLI and localhost gateway for LLM apps, agents, and experiments. Store your provider keys once on your own machine, then give each app a scoped 21pins token instead of handing out real OpenAI, OpenRouter, Anthropic, DeepSeek, Venice, Hetzner, Maple, Gemini, or Ollama credentials.\n\nIt speaks the OpenAI-compatible `/v1/chat/completions` shape, so many tools can use it by changing only the base URL, API key, and model name.\n\n## Why use it?\n\n- **Stop pasting real provider keys into every prototype.** Use one local 21pins token per app or agent.\n- **Never ship a real API key in a repo by mistake.** Apps talk to `127.0.0.1`; provider keys stay in your local 21pins state file.\n- **Give agents narrower permissions.** A Pi token can have `proxy:chat,usage:read` without exposing your upstream OpenRouter key.\n- **See surprise bills before they become surprise bills.** 21pins records local token usage and estimated API cost for routed chat calls.\n- **Switch providers without rewriting every client.** Route models like `openrouter/openai/gpt-4o-mini`, `openai/gpt-4o-mini`, or `ollama/llama3.2` through one local gateway.\n- **Tinker with less anxiety.** Build weird agent workflows, demos, and side projects without spraying secrets across shells, env files, and dashboards.\n\n## Install\n\n```bash\nnpm install -g 21pins\n```\n\nThen initialize local state:\n\n```bash\n21pins init\n```\n\nYour local state is separate from the npm package. Upgrading or reinstalling the npm package does not delete your stored keys, tokens, grants, receipts, or usage rows.\n\nDefault state paths:\n\n```text\nLinux:  ~/.config/21pins/state.json\nmacOS:  ~/Library/Application Support/21pins/state.json\n```\n\nSet `PINS21_STATE_PATH` if you want to store state somewhere else.\n\n## Quickstart: Pi → 21pins → OpenRouter\n\nAdd your OpenRouter key once:\n\n```bash\n21pins key set openrouter --value \"$OPENROUTER_API_KEY\"\n```\n\nCreate a scoped token for Pi or another local app:\n\n```bash\n21pins token create pi --scopes proxy:chat,usage:read\n```\n\nStart the local gateway:\n\n```bash\n21pins serve --port 8787\n```\n\nConfigure your OpenAI-compatible client:\n\n```text\nBase URL: http://127.0.0.1:8787/v1\nAPI key:  the 21pins token, not your OpenRouter key\nModel:    openrouter/openai/gpt-4o-mini\n```\n\n21pins forwards the request with your stored OpenRouter key and records local usage/cost data when the upstream response includes usage.\n\n## JavaScript example\n\n```js\nimport OpenAI from \"openai\";\n\nconst client = new OpenAI({\n  apiKey: process.env.PINS21_TOKEN,\n  baseURL: \"http://127.0.0.1:8787/v1\",\n});\n\nconst response = await client.chat.completions.create({\n  model: \"openrouter/openai/gpt-4o-mini\",\n  messages: [{ role: \"user\", content: \"Say pong.\" }],\n});\n\nconsole.log(response.choices[0].message.content);\n```\n\n## Usage and cost dashboard\n\nCreate your app token with `usage:read`, start the gateway, then open:\n\n```text\nhttp://127.0.0.1:8787/ui\n```\n\nOr fetch JSON:\n\n```bash\ncurl -H \"Authorization: Bearer $PINS21_TOKEN\" \\\n  http://127.0.0.1:8787/v1/usage\n```\n\n`/ui` and `/v1/usage` are loopback-only. `/v1/usage` requires the `usage:read` scope.\n\n## Providers\n\n21pins currently wires:\n\n- OpenAI\n- OpenRouter\n- Anthropic\n- DeepSeek\n- Venice\n- Hetzner\n- Maple / TryMaple\n- Gemini\n- Ollama\n\nList providers:\n\n```bash\n21pins key providers\n```\n\nSync model catalogs where supported:\n\n```bash\n21pins models sync\n21pins models list --provider openrouter --search gpt\n21pins models choose --provider openrouter --search gpt\n```\n\n## Security model\n\n21pins is intentionally boring:\n\n- provider keys live in a local state file, not in this npm package\n- app tokens are shown once when created\n- the default gateway binds to `127.0.0.1`\n- usage endpoints are loopback-only\n- npm install uses optional platform packages, not a remote-download postinstall script\n\nStill treat every 21pins token like a bearer credential. If you paste it somewhere unsafe, rotate it.\n\n## More docs\n\n- Website: <https://21pins.com>\n- GitHub: <https://github.com/automatethething/21pins>\n- Packaging notes: <https://github.com/automatethething/21pins/blob/main/docs/packaging.md>\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-c53d51ff455fd4702ae67cf2022ae3a3"}