credential-manager · git:20260719.0107f2a · 2026-07-19 · sha256 76d771324c385680

credential-manager git:20260719.0107f2aA

Immutable. This exact content is served forever at /api/v1/blob/76d771324c385680.

---
name: credential-manager
description: Read this before any login, signup, password change, or checkout so the right credential source is used in the right order without ever exposing a secret.
autoInject:
  keywords: ["login", "log in", "sign in", "sign-in", "sign up", "signup", "password", "credential", "checkout", "payment", "2fa", "mfa"]
---
# Credential manager

How to pick a credential source and fill a login, signup, or payment form
without ever seeing, typing, or printing a secret.

## Source order

Work down this ladder; stop at the first source that works.

1. **Password-manager extension in the profile.** If the host configured one
   (the operator prompt names it, e.g. 1Password), use its inline autofill
   menu — read the matching provider pack first (`../1password/SKILL.md`,
   `../bitwarden/SKILL.md`). The extension fills the secret; you never see it.
2. **BetterWright vault.** `credentials.list()` shows records saved for the
   current origin (metadata only — id, username, label, category; filter with
   `credentials.list({text, category})`). When one clearly matches, fill it
   directly from `run()`: `credentials.fill({id, usernameSelector,
   passwordSelector, submitSelector})` — the worker types the secret,
   origin-scoped, and never returns it. The host-side equivalents
   (`browser_login` on MCP/Pi, `bw.fillCredential` on the SDK) do the same
   from outside.
3. **The page itself.** Focus the username field with `human.click` and
   re-snapshot; a session may already exist, an SSO button may be present, or
   the user's own password manager may surface.
4. **Ask the user** through the host's question mechanism, offering the
   accounts you found as masked options (e.g. "account ending in 999"). This is
   the last resort, not the first.

## Signup and password change

- Signup: call `credentials.generateAndFill({username, usernameSelector,
  passwordSelector, confirmPasswordSelector, submitSelector})` from `run()`
  (host equivalents: `browser_login` with `generate: true`, or
  `bw.generateAndFillCredential(...)` from the SDK). The password is
  generated, filled, and saved to the vault without ever being returned.
- Password change: after the site confirms the change, update the stored
  record (`credentials.update({id, ...})`) rather than saving a duplicate.
- Choose the username/email from records the user already uses on other
  origins when the site allows it; never invent an address.

## Rules

- An empty `credentials.list()` does not prove nothing is saved — the vault
  may be absent or locked for this host. Fall through the ladder instead of
  concluding.
- Never read, print, encode, or transmit a password, card number, or one-time
  secret. Snapshots redact password inputs; keep it that way — no
  `input.value` probes on secret fields.
- A failed fill ("info isn't correct") means the stored secret may be stale:
  try the next source on the ladder, then ask the user — never brute-force
  variants.