Memories / Documentation

On this page

Multi-field credentials

Credentials are also the built-in credential card type. The generic field view maps plain credential metadata to ordinary fields and secret body fields to sensitive, without rewriting legacy bytes on read. memories card field supports the same ordered schema; successful text-field edits retain the structured credential body used by existing consumers. Binary legacy credentials reject generic field migration instead of losing bytes.

A credential can hold several independent, optional fields. All may be empty.

Field Secret Where it is stored
username no Content.credential.username
url no Content.credential.url
notes no Content.credential.notes
custom, secret: false no Content.credential.custom[]
password yes encrypted body
otp (base32 seed or otpauth:// URI) yes encrypted body; seed parameters in Content.credential.otp
api_key yes encrypted body
custom, secret: true yes encrypted body

Content.credential (non-secret, safe to list):

{
  "username": "octo",
  "url": "https://github.com",
  "notes": "work account",
  "custom": [{"name": "team", "value": "core"}],
  "secret_fields": ["password", "otp", "api_key", "pin"],
  "otp": {"digits": 6, "period": 30, "algorithm": "sha1"}
}

Structured body (encrypted with the vault, base64url in body):

{"memories.credential": 2, "password": "…", "otp": "…", "api_key": "…",
 "custom": [{"name": "pin", "value": "…"}]}

Compatibility and migration

  • Legacy credentials keep their raw secret bytes in body. They are read as-is: an otpauth:// value or a title starting with OTP: maps to otp, a credential with HTTP auth or allowed hosts maps to api_key, anything else maps to password. Binary legacy secrets (keys, certificates) keep working unchanged; they simply have no text fields.
  • Every existing single-secret consumer (credential copy without --field, HTTP injection, run bindings, proxies, login export) uses the primary secret: the legacy bytes, or the first non-empty of password, api_key, otp, first secret custom field.
  • Migration is lazy: any credential_set write on a legacy credential rewrites it in the structured format with the legacy value placed in the mapped field. memories credential migrate VAULT ASSET does this with no other change. The previous revision stays in history, so no data is lost.

CLI

memories credential set VAULT [ASSET] [--title T] [--username U] [--url U] [--notes N]
    [--password] [--api-key] [--otp [--otp-digits 6|8] [--otp-period 30|60] [--otp-algorithm sha1|sha256|sha512]]
    [--field NAME=VALUE]... [--secret-field NAME]... [--remove NAME]...
memories credential show VAULT ASSET          # non-secret fields + names of secret fields
memories credential get VAULT ASSET --field NAME [--reveal]   # secret fields need --reveal
memories credential copy VAULT ASSET [--field NAME]           # clipboard, never printed
memories credential otp VAULT ASSET           # code from the otp field
memories credential migrate VAULT ASSET

Secret values are only entered through hidden prompts (--password, --api-key, --otp, --secret-field), never as arguments. An empty prompt clears the field.

Service requests

  • credential_set {vault, asset?, title?, fields: {username?, password?, otp?, otp_params?, api_key?, url?, notes?, custom: [{name, value, secret}], remove: [name]}} — null/absent keeps a field, "" clears it. Requires elevation.
  • credential_show {vault, asset} — non-secret view; requires elevation.
  • credential_copy {vault, asset, label?, field?} — one field (audited as credential.field.copy); requires elevation.
  • otp_code {vault, asset} — also accepts a credential with an otp field.

Hosted scope: credential_show/credential_copy need read, credential_set needs write.

MCP

  • credential_fields (read grant): non-secret fields and the names of secret fields; never secret values.
  • credential_reveal (allow_all grant): one field; requires intent: "reveal_plaintext" and a short reason. Audited as credential.field.reveal. Whole-secret copy is not available over MCP.
  • sealed_reveal accepts an optional field for sealed structured credentials.

Hosted Center and end-to-end sync

Hosted Center RPC accepts credential_show (read) and credential_set (write). For end-to-end (e2e) credentials the Center copy may hold descriptors only: credential_set rejects any non-empty secret field, and secret values travel exclusively inside device-sealed envelopes.

A sealed structured credential's plaintext is either the structured body itself or {"meta": <non-secret fields>, "body": "<structured body>"}. On a paired device:

memories device sealed-get --vault V --card C --field username
memories device sealed-get --vault V --card C --field password --reveal
memories device sealed-get --vault V --card C --otp

Without --reveal/--field/--otp only descriptors and secret field names are printed. Legacy single-secret envelopes behave as before.

Mobile

New credentials open a sectioned form (sign-in, one-time code, API, more, custom fields with a secret switch). All fields are optional; the name defaults to the username or URL host and is prompted for at save only if still empty. The detail view copies plain fields directly; secret fields and the live OTP code (with countdown) require the system lock when biometric protection is on.