16 KiB
Bitwarden / Vaultwarden — TU vault de bot
Qué es esto
Skill que te da acceso a tu propia cuenta (claudecode0@nucleoriofrio.com)
en el Vaultwarden del beneficio (vault.nucleoriofrio.com). Es paralela a tu
cuenta claudecode0 de Gitea — NO es la cuenta del usuario humano.
Punto importante para no confundirte:
- Tu vault personal contiene tus credenciales de bot: PATs, API keys, tokens de servicios que necesitás como agente para hacer tu trabajo.
- El usuario humano tiene su propio vault separado en el mismo Vaultwarden, con sus credenciales personales — no las tocás vos, no las leés vos.
- El usuario humano sí tiene acceso administrativo a tu cuenta (puede ver,
modificar y borrar items en TU vault) porque el
.envcon tu master password vive en su PC y él es admin del servidor. Eso es para auditoría — los items funcionalmente son tuyos. - Si el usuario te pide "guardá esto", lo guardás en TU vault. Si te pide "buscá esto", buscás en TU vault. Si te pide algo personal de él que él no guardó en TU vault, decile que no lo tenés.
Funciona vía bw serve: el CLI oficial de Bitwarden levanta un servidor REST local
en 127.0.0.1:8087 y la skill llama a esos endpoints. La encriptación/desencriptación
del vault pasa local con master password. El server de Vaultwarden solo recibe blobs
encriptados.
- Server:
https://vault.nucleoriofrio.com - Tu cuenta:
claudecode0@nucleoriofrio.com - Auth: master password (en
.env) → email+password login → session cacheada - Modelo de permisos: read + create. PUT/DELETE/PATCH bloqueados por script guard
- Bind: solo
127.0.0.1(no exposed a la LAN)
Cómo invocarla correctamente
Antes de cualquier query:
- Verificá
~/.claude/skills/bitwarden/.env. Si no existe, avisá al usuario:cp ~/.claude/skills/bitwarden/.env.example ~/.claude/skills/bitwarden/.envy pedí que complete los valores (master password + credenciales). - Primer uso de la sesión: el primer
query.sharrancabw serveautomáticamente (víaserve-up.sh). Tarda ~3s. Las llamadas siguientes son instantáneas. - Si
query.shdevuelve 401: la session expiró o el vault está locked. Corrébash ~/.claude/skills/bitwarden/scripts/setup.shpara re-unlock.
El helper canónico es query.sh:
~/.claude/skills/bitwarden/scripts/query.sh /status
~/.claude/skills/bitwarden/scripts/query.sh /list/object/items
~/.claude/skills/bitwarden/scripts/query.sh "/object/item/<uuid>"
Ver endpoints.md para la cheat sheet completa.
Modelo de seguridad (read + create)
Tres capas:
- Server-side (la que importa para org NucleOS): la cuenta
claudecode0está en el org "NucleOS" con role User + collections con permiso "Can view" → server rechaza cualquier POST/PUT/DELETE en collections del org. Esto te garantiza no romper nada compartido. - Script guard (la que importa para vault personal):
query.shrechaza-X PUT/DELETE/PATCHy los POST a/move/*,/restore/*,/confirm/*,/object/attachmentantes de salir a la red. Defensa contra modify/delete en el vault personal del bot, donde server-side no podés limitarte a vos mismo. - bw serve bind a 127.0.0.1: nadie en la LAN puede pegarle. Solo procesos locales del usuario.
⚠️ El bw CLI tiene una vulnerabilidad histórica conocida (clients#3932): cualquier proceso del usuario en este equipo puede pegar a
127.0.0.1:8087mientras esté unlocked. En la PC personal del usuario es aceptable. Si esta skill se mueve a un equipo compartido, hay que repensar.
⚠️ El script guard NO es perfecto: se bypass-ea llamando
bwdirecto. Si la auto-mode runtime te bloquea unbw deleteo similar, respetá el bloqueo — incluso para limpieza de pruebas, pedile al usuario que lo borre desde web.
Cuándo usar qué endpoint
Recordá: cuando el usuario diga "buscá", "guardá", "tenés", se refiere a TU vault (claudecode0). Si te pide algo que no está y suena a personal del usuario humano, decile que probablemente está en SU vault — no en el tuyo.
Usuario te pide "buscá en tu vault si tenés X"
# Buscar por nombre o URL en TU vault
~/.claude/skills/bitwarden/scripts/query.sh "/list/object/items?search=gitea"
# → tomá el id del match. Si necesitás el password en plaintext:
~/.claude/skills/bitwarden/scripts/query.sh "/object/password/<id>"
Usuario te pide "qué tenés guardado vos / inventario de tu vault"
~/.claude/skills/bitwarden/scripts/query.sh /list/object/items \
| python -c "import json,sys; [print(i['name'], '|', i.get('login',{}).get('username','-')) for i in json.load(sys.stdin)['data']['data']]"
Usuario te pide "generame un password" (utility, no toca vault)
~/.claude/skills/bitwarden/scripts/query.sh "/generate?length=24&uppercase&lowercase&numbers&special"
# Para passphrase:
~/.claude/skills/bitwarden/scripts/query.sh "/generate?passphrase=true&words=4&separator=-&capitalize"
Usuario te pide "guardá esto en tu vault"
Esto agrega un item a TU vault. Antes de hacerlo:
- Listá primero con
?search=<name>para ver si ya tenés algo con ese nombre. Vaultwarden permite duplicados (no overwrite), y crear sin chequear te deja con dos items idénticos que vos no podés mergear (DELETE bloqueado). - Pedí el template para no equivocarte con el schema:
~/.claude/skills/bitwarden/scripts/query.sh /object/template/item.login - Construí el JSON con
name,login.username,login.password,login.uris. - POST:
~/.claude/skills/bitwarden/scripts/query.sh -X POST \ -H 'Content-Type: application/json' \ -d '{"organizationId":null,"folderId":null,"type":1,"name":"...","login":{"username":"...","password":"...","uris":[{"uri":"https://..."}]}}' \ /object/item - Si la credencial venía del usuario en el chat, confirmale al usuario
"guardé
<name>en mi vault con username<username>" sin re-mostrar el password. Si la generaste vos, podés mostrarla una vez al confirmar.
Usuario te pide TOTP de algo que tenés guardado
# Buscá el item primero, después:
~/.claude/skills/bitwarden/scripts/query.sh "/object/totp/<item-id>"
# → devuelve el código actual (rota cada 30s)
Usuario te pide "chequeá si esa password fue expuesta"
~/.claude/skills/bitwarden/scripts/query.sh "/object/exposed/<item-id>"
# → { exposed: <count en HIBP> }
Usuario te pide "leé el password compartido X del org NucleOS"
Si estás invitado al org "NucleOS" con permiso "Can view" en alguna collection:
# Listar tus orgs
~/.claude/skills/bitwarden/scripts/query.sh /list/object/organizations
# Listar collections del org a las que tenés acceso
~/.claude/skills/bitwarden/scripts/query.sh "/list/object/org-collections?organizationid=<id>"
# Listar items del org
~/.claude/skills/bitwarden/scripts/query.sh "/list/object/items?organizationid=<id>"
# Leer password de un item específico
~/.claude/skills/bitwarden/scripts/query.sh "/object/password/<item-id>"
Estos items son del org, no tuyos personales. El usuario humano y otros miembros del org también los ven. NO podés modificarlos ni borrarlos (server-side rechaza por permiso "Can view").
Reglas de comportamiento
Cuando devolvés passwords/secrets al usuario
- El usuario humano tiene acceso administrativo a TU vault, así que técnicamente puede ver todo igual desde web. Mostrar un password tuyo en el chat cuando él te lo pide explícitamente está bien — no estás filtrando nada.
- Pero no muestres passwords espontáneamente. Si te piden "qué tenés
guardado", listá
name+username, NO password. Si quieren el password, te lo van a pedir aparte. - Nunca cites un password en un summary, commit message, PR description, ni en cualquier output que pueda quedar en git history, tickets, o canales externos — incluso siendo "tu" password de bot, igual es un secret.
- Si te piden "verificá que tengo guardado X", alcanza con devolver "✓ tengo un item llamado X con username Y" — no hace falta el password para verificar existencia.
Cuando creás items nuevos en TU vault
- Listá primero con
?search=<name>para chequear duplicados. Vaultwarden permite crear varios items con el mismo nombre (no overwrite), y como vos no podés borrar (DELETE bloqueado), si te equivocás vas a tener basura permanente que solo el usuario humano puede limpiar desde web. - Si la password te la pasa el usuario, no la repitas en el chat — confirmá con "guardé el item con username X" sin re-mostrar la password.
- Si la password la generás vos (con
/generate), podés mostrarla una vez al confirmar el guardado para que el usuario sepa qué se guardó. No la repitas en respuestas posteriores. - Etiquetá bien el
namepara no confundirte vos en el futuro: usá nombres descriptivos comogitea-pat-claudecode0oopenai-api-key-bot, nogiteaa secas (que se confunde con el password de Gitea del usuario humano, que NO es tuyo).
Cuando el usuario te pide modificar/eliminar algo de TU vault
- El guard te lo bloquea por diseño. Opciones:
- Decile al usuario que él lo haga desde el web vault (él tiene acceso).
- Pedile autorización explícita para bypass-ear vía
bwCLI directo. En ese caso, la línea exacta:BITWARDENCLI_APPDATA_DIR=~/.claude/skills/bitwarden/.cache/bw \ BW_SESSION=$(cat ~/.claude/skills/bitwarden/.cache/session) \ bw delete item <id>
- No bypass-ees por iniciativa propia ni para "limpieza" de pruebas. La auto-mode runtime te va a frenar y va a tener razón. Si vos creaste basura por error, asumí el costo y dejala.
Cuando el usuario te pide algo que NO es tuyo
- Si suena a credencial personal del usuario humano (ej. "buscame mi password
de Netflix"), avisá: "eso debería estar en TU vault personal, no en el mío.
Yo solo tengo acceso a la cuenta
claudecode0". No intentés "buscar igual por las dudas". - Si el usuario te pide algo que crees que está en una collection del org NucleOS pero no lo encontrás, podría ser que no estés invitado a esa collection o que el item no exista. Decile.
Errores típicos
401 unauthorizedo output de bw "vault is locked" → corrésetup.shConnection refuseda localhost:8087 →bw servemurió, corréserve-up.sh403 forbiddenen endpoints del org → permiso "Can view" rechaza writes, esperado y correcto400 bad requesten POST → schema del item está mal, pedíGET /object/template/item.login(o.card, etc.)
Lifecycle: cuándo correr cada script
| Script | Cuándo |
|---|---|
setup.sh |
(a) Primera vez. (b) Cuando session expira (401). (c) Cuando se cambió la master password en el .env |
serve-up.sh |
Idempotente. Lo llama query.sh automáticamente. Solo lo corrés a mano si querés calentar el daemon antes de un batch de queries |
serve-down.sh |
Cuando querés liberar el puerto/proceso (raro: el daemon es liviano y no consume mientras no recibe queries) |
query.sh |
Para todo lo demás |
bw serve queda corriendo en background entre invocaciones de Claude Code (es
un proceso del sistema, no de la sesión). Si reiniciás la PC, la primera query
después del reboot relanzará el daemon.
Setup inicial (lo hace el usuario UNA vez)
1. Crear cuenta claudecode0 en Vaultwarden web
- Login admin a
https://vault.nucleoriofrio.com/adminconADMIN_TOKEN - Users → Invite User → email
claudecode0@nucleoriofrio.com - (Como no hay SMTP, no llega mail — alcanza con que quede el invite verificado)
- Ir a
https://vault.nucleoriofrio.com/#/register(logueado anónimo) - Email:
claudecode0@nucleoriofrio.com, master password: la que vayas a poner en.env - Submit → cuenta queda activa
- No usar SSO — actualmente está roto en producción (discovery falla desde dentro
del container, ver task spawn-eada). Email+password directo funciona porque
SSO_ONLY=false.
2. Crear .env local
cp ~/.claude/skills/bitwarden/.env.example ~/.claude/skills/bitwarden/.env
# Editar y completar BW_PASSWORD, BW_CLIENTID, BW_CLIENTSECRET
chmod 600 ~/.claude/skills/bitwarden/.env # best-effort en Windows
Aunque el .env tiene campos para
BW_CLIENTIDyBW_CLIENTSECRET, la skill no los usa actualmente. Login va por email+password (bw login --apikeytiene un bug en bw CLI 2026.4.x: deja el cryptographic state null y rompe el unlock posterior). Los campos están por si se arregla el bug y queremos volver a API key.
3. Correr setup
~/.claude/skills/bitwarden/scripts/setup.sh
Esperado: → Listo: unlocked | claudecode0@nucleoriofrio.com | https://vault.nucleoriofrio.com
4. Probar
~/.claude/skills/bitwarden/scripts/query.sh /status
# → JSON con status: unlocked
5. (Opcional) Org NucleOS
Si existe organization "NucleOS" en Vaultwarden, el usuario humano debe invitar
a claudecode0@nucleoriofrio.com con role User + collections con permiso
Can view desde el web vault. Después la skill puede leer (no escribir) lo
del org.
Qué NO hace esta skill
- No modifica ni elimina (PUT/DELETE bloqueados, POST en endpoints destructivos bloqueado).
- No usa SSO (el flow está roto en producción — task spawn-eada para fix).
- No expone MCP — Bash + curl, igual que unifi y whatsapp.
- No mantiene cache de items — cada query golpea localhost:8087 que a su vez consulta vault local desencriptado.
- No comparte items con otros users/orgs (
/move,/sharebloqueados). - No accede al vault personal del usuario humano — son cuentas separadas en Vaultwarden, distintas master passwords, distintos vaults encriptados.
Archivos de la skill
| Archivo | Qué tiene |
|---|---|
SKILL.md |
Este archivo |
endpoints.md |
Cheat sheet de endpoints bw serve |
.env.example |
Plantilla de config |
.env |
Config local (no versionado, contiene master password) |
scripts/setup.sh |
One-time/recovery setup (config server + login + unlock + sync) |
scripts/serve-up.sh |
Asegura bw serve arriba (idempotente) |
scripts/serve-down.sh |
Mata bw serve |
scripts/query.sh |
Helper REST con auth + read+create guard |
.cache/session |
Session token cacheada (chmod 600) |
.cache/serve.pid |
PID de bw serve |
.cache/serve.log |
stdout/stderr de bw serve (debug) |
.cache/bw/ |
Data dir aislado de bw CLI (vault encriptado local, server config) |
Referencias
endpoints.md— cheat sheet de endpoints- Doc oficial CLI: https://bitwarden.com/help/cli/
- Vault Management API spec: https://bitwarden.com/help/vault-management-api/
- Vaultwarden self-hosted (compatible 100% con bw CLI): https://github.com/dani-garcia/vaultwarden
- Stack en producción:
nucleo-infra/infrastructure/vaultwarden/stack.yml