bitwarden/exploring-bitwarden-data
Read-only exploration of a local Bitwarden development database — answer business questions from live data, verify seeded fixtures, and introspect schema. Use whenever the user wants to query, count, look up, verify, or explore data in a local Bitwarden database ("how many orgs/users/ciphers", "show me collections", "check what the seeder created", "look up user X", "which orgs have feature Y"), even without the word SQL. Not for authoring stored procedures, migrations, or repository code (use writing-database-queries), and not for seeding or modifying data.
npx skills add https://github.com/bitwarden/server --skill exploring-bitwarden-data
Read-only access to a local Bitwarden database, across all three dev providers.
SELECT, WITH (CTEs), and INFORMATION_SCHEMA / sys.* introspection.cat, printenv, or hexdump any password env var. Set passwords inline on the command (e.g., SQLCMDPASSWORD="$BW_MSSQL_PASSWORD" sqlcmd ...); never export them.(N rows affected), Query OK) before presenting.<<'SQL') — without quotes, bash expands $ inside the SQL before the database CLI sees it, breaking column references.First arg picks the provider — mssql (default), mysql, or postgresql. Read the matching provider reference before composing SQL.
| Provider | Env prefix | CLI | Reference | Status |
| ---------- | --------------- | -------- | ------------------------------------------------------------------------ | --------- |
| MSSQL | BW_MSSQL_* | sqlcmd | references/providers/mssql.md | Ready |
| MySQL | BW_MYSQL_* | mysql | references/providers/mysql.md | Ready |
| PostgreSQL | BW_POSTGRES_* | psql | references/providers/postgresql.md | Ready |
Don't compose SQL from a generic mental model of how a vault schema "probably" looks — and don't expect this skill to inventory the schema for you. The repo already does, and it stays current when this file wouldn't:
src/Sql/dbo/, or live introspection via references/schema-discovery-queries.md.dbo].UserCipherDetails for "what can user X see", [dbo].[UserCollectionDetails for collection permissions. They encode member status, org enablement, and direct-over-group grant precedence that is easy to rebuild subtly wrong.Semantics the schema itself cannot tell you — each of these flipped a real eval case that unaided Claude got wrong (evidence in evals/baseline-results.md; that is also the bar for adding a rule here).
OrganizationUser.Status = 2 (Confirmed). "Active" is genuinely ambiguous — the occupied-seat definition (Status IN (0,1,2), used by the seat-count procs) is a defensible rival reading, so state which one the question needs. Full lifecycle (including Staged and Revoked-with-restore) is documented in OrganizationUserStatusType.cs.Cipher.Archives — per-user JSON keyed by UPPERCASE user GUID — not in the ArchivedDate column. ArchivedDate exists on the table but the archive flow never writes it (Cipher_Archive does JSON_MODIFY on Archives); querying it returns zero forever while looking perfectly reasonable. Favorites and Folders use the same per-user JSON shape, so interpolate keys from a UNIQUEIDENTIFIER (SQL Server renders them uppercase; JSON keys are case-sensitive).Organization.Enabled = 1 is the active flag. Organization.Status is the provider-management lifecycle (Pending/Created/Managed), and Plan is a display string — aggregate and filter on PlanType.| Reference | When to read |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| references/sources.md | Finding the source file for any table, enum, or canonical function |
| references/schema-discovery-queries.md | Live introspection — list tables, describe columns, find FKs, view bodies |
| references/providers/mssql.md | MSSQL connection, sqlcmd invocation patterns, dialect notes |
Take bitwarden/exploring-bitwarden-data from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.