# Profile Use

> Safely use a user's private local personal profile to help fill registration, signup, checkout, banking, KYC, and onboarding forms. Use when the user asks to enter or reuse identity details such as name, address, phone, postal code, email, birthdate, payment card, bank account, tax ID, or other personal data. Prioritize privacy, redaction, consent before submission, and local/iCloud/encrypted profile sources rather than storing personal data in chat or Git.

- Skill: `leeguooooo/profile-use` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add leeguooooo/profile-use`
- Raw SKILL.md: https://api.skillmd.com/api/skills/leeguooooo/profile-use/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: leeguooooo (https://skillmd.com/u/leeguooooo)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/leeguooooo/profile-use

---


# Profile Use

Use a private profile as the source of truth for repetitive registration and checkout fields. The skill helps map form labels to profile fields, fill only what is needed, and keep sensitive values out of chat, logs, screenshots, repos, and PRs.

## Privacy Rules

1. Never invent personal data. If a field is missing, ask the user or leave it blank.
2. Do not store real personal data in the skill repo, memory, issue trackers, PRs, screenshots, or final responses.
3. Use redacted summaries by default. Reveal full values only when the user explicitly asks and the current task requires it.
4. Treat payment cards, bank accounts, government IDs, tax IDs, passwords, security answers, and medical fields as high sensitivity. Ask for explicit confirmation before entering or revealing them.
5. Do not submit a registration, KYC, checkout, banking, or payment form until the user explicitly approves the final submit action.
6. If browser automation is used, verify the real domain and purpose before filling. Stop on suspicious, unrelated, or typosquatted domains.

## Profile Source

Prefer the helper script:

```bash
python3 scripts/profile_use.py path
python3 scripts/profile_use.py doctor
python3 scripts/profile_use.py init --profile personal
python3 scripts/profile_use.py show --profile personal
python3 scripts/profile_use.py values --profile personal
python3 scripts/profile_use.py values --profile personal contact.email address.postal_code
python3 scripts/profile_use.py get --profile personal contact.email address.postal_code
python3 scripts/profile_use.py set --profile personal address.postal_code "1000001"
python3 scripts/profile_use.py list-fields --profile personal --filled
```

### Redacted vs. raw: pick the right command

This is the most important rule for autofill. Two output modes exist and they are not interchangeable:

- **`values`** returns RAW values. Use it for every value you actually type into a form. With no fields it dumps all filled low/medium fields as a flat `{dotpath: value}` map ready to map onto form labels; it excludes high-sensitivity fields unless you name them or pass `--include-sensitive`.
- **`show` / `get`** return REDACTED values by default (names, email, phone, address lines, card, bank, IDs, notes are masked). Use these only to orient or to report back to the user. Pass `--reveal` to unmask.

NEVER type a redacted/masked value into a form. `get contact.email` returns `t***@example.com`; filling that breaks the registration. To fill, use `values contact.email` (or `get --reveal`). When in doubt for filling: use `values`.

Default location order:

1. `$PROFILE_USE_DIR` (legacy `$PERSONAL_AUTOFILL_DIR` is still honored)
2. `$HOME/Library/Mobile Documents/com~apple~CloudDocs/Agent Profiles/profile-use`
3. `$HOME/.config/profile-use`

A pre-rename `personal-autofill` directory that still holds data is used as a fallback when the `profile-use` directory does not exist yet.

The iCloud rule checks the iCloud Drive root (`com~apple~CloudDocs`) and creates `Agent Profiles/profile-use` on first write. Use `doctor` when a profile unexpectedly lands in `.config`.

Use `references/profile-template.json` for the editable shape. Use `references/profile-schema.json` for field names and sensitivity hints.

## Growing The Profile

Expect the profile to grow over time as real registrations reveal new fields. When a form asks for information that is not already in the profile:

1. Ask the user for the value only if it is required for the current registration.
2. Decide whether it is reusable. Save stable values such as alternate emails, shipping addresses, invoice names, furigana, company details, and country-specific address variants. Do not save one-time codes, session tokens, CAPTCHA text, temporary invitation links, or site passwords.
3. Ask before writing high-sensitivity or newly invented field paths.
4. Add the field with `set`:

```bash
python3 scripts/profile_use.py set --profile personal identity.name_kana "..."
python3 scripts/profile_use.py set --profile personal address.jp.prefecture "..."
python3 scripts/profile_use.py set --profile personal preferences.newsletter_opt_in false --json
```

5. Confirm with redacted reads:

```bash
python3 scripts/profile_use.py get --profile personal identity.name_kana address.jp.prefecture
```

Use flexible nested paths when a country, site, or tenant needs a special variant. Examples: `address.jp.*`, `address.us.*`, `contact.work_email`, `invoice.jp.qualified_invoice_name`.

### Proactive Capture (offer to record, don't wait for a form)

Profile growth is not limited to autofill. During **any** task — answering a tax question, reading a chat, helping with onboarding paperwork — durable personal facts surface that the user will likely need again. When that happens, **proactively offer to record them**, then write only after the user agrees:

1. Notice the fact is **stable and reusable**, not one-time. Good: family members' birthdates / relationships, dependent and tax-residency status, employer / salary structure, an HR- or authority-confirmed requirement (what document is needed, who handles it), a recurring address or invoice variant. Skip: one-time codes, transient amounts, session/case context that won't recur.
2. **Ask before writing.** Say what you'd save and the dotpath (e.g. "记进 `family.father.birthdate` / `tax.jp.dependents.*`?"). Get a yes first; never silently persist. The exception is when the user already said "record this" / "记一下" — then write and report.
3. Pick a sensible path under an existing section before inventing a new top-level one; flexible nested paths are fine (`family.*`, `tax.jp.dependents.*`). Treat new high-sensitivity paths and any `payment`/`bank`/`government_id`/`tax`/birthdate value as confirmation-gated even when the user broadly agreed to "record stuff".
4. After writing, confirm with a redacted `list-fields --filled` / `get`, and report the dotpath — not the raw value — back to the user.

Keep all other rules in force: redaction by default, nothing high-sensitivity revealed in the final response, and the profile JSON stays the store of record (not chat, memory, or Git).

## Fill Workflow

1. Identify the form's site, purpose, and profile to use. Default to `personal` unless the user names another profile such as `work`, `family`, or `jp`.
2. Inspect the form labels and required fields. Build a mapping from labels to profile paths; do not rely only on placeholder text.
3. Orient with redacted `show` to see the shape, then read the exact values you will type with `values` (raw). Use `values` with no fields to get a flat map of all filled low/medium fields at once.
4. Fill low-sensitivity fields directly when the user asked for autofill, using the raw `values` output. Examples: name, email, phone, postal code, `address.country` / `address.region` / `address.city`.
5. For high-sensitivity fields (`payment`, `bank`, `government_id`, `tax`, birthdate, gender, and the street-address lines `address.line1` / `address.line2`), show a redacted summary and ask for confirmation before filling; fetch the raw value with an explicit `values address.line1` (or `values payment.card.number`) only at the moment of filling. These are excluded from the no-field `values` dump, so you must name them.
6. Before submission, summarize the fields that were filled using redacted `show`/`get` values and wait for an explicit submit approval.

## Field Mapping Hints

- `identity.full_name`: full legal name or display name, depending on the form.
- `identity.family_name`, `identity.given_name`: split-name fields.
- `contact.email`, `contact.phone`, `contact.phone_country_code`: email and telephone fields.
- `address.country`, `address.region`, `address.city`, `address.postal_code`: address fields (low sensitivity). `address.line1`, `address.line2`: the precise street address — high sensitivity, masked in `show` and excluded from the no-field `values` dump.
- `payment.card.*`: card fields; always high sensitivity.
- `bank.*`: bank transfer or withdrawal fields; always high sensitivity.
- `government_id.*`, `tax.*`: identity verification fields; always high sensitivity.
- `preferences.*`: marketing opt-in, locale, newsletter, and delivery preferences.
- `invoice.*`: billing name, tax invoice name, receipt name, or business invoice details.
- `site_overrides.<domain>.*`: a value required only by one service; use this sparingly.

If a site has country-specific formatting rules, preserve the profile value unless the form rejects it. Normalize only after checking the visible validation message.

### Output formats for `values`

Two flags on `values`, for the two conversions agents kept doing by hand at
fill time:

- `--phone-format domestic|e164` — `contact.phone` as the trunk-prefixed
  national number (`07012345678`) or E.164 (`+817012345678`). Only applies when
  `contact.phone_country_code` is on file; without it there is no honest way to
  tell `+81 70` from a national `070`, so the value is returned as stored.
- `--format jp-fullwidth` — ASCII digits, letters and hyphens in every returned
  string as full-width (`201-0001` → `２０１－０００１`, `25番57-402号` →
  `２５番５７－４０２号`) for Japanese forms that reject half-width input. Kana
  and kanji are untouched.

```bash
python3 scripts/profile_use.py values contact.phone --phone-format domestic
python3 scripts/profile_use.py values address.jp.kana_remainder --format jp-fullwidth
```

### Conventional paths for recurring cases

The schema is free-form nested paths, so any of these can be stored today without
a code change. Use these exact paths anyway. The failure mode is not "the field
cannot be stored" — it is that each agent invents its own path (`payment.hk_bank`
one week, `bank.hk` the next), and the next agent cannot find what the last one
saved. Converging matters more than the names being perfect.

**Names as printed on an ID.** Residence cards, passports and driver's licences
print a romanised name whose order may not match `identity.family_name` /
`identity.given_name`. Japanese forms routinely want that exact string in the
漢字 slot plus a separate kana line.

- `identity.romaji.family_name`, `identity.romaji.given_name`
- `identity.name_on_id`: the name exactly as printed, including its order
- `identity.kana.family_name`, `identity.kana.given_name`

**Japanese structured address.** Forms auto-fill 都道府県/市区町村/町域 from the
郵便番号 and then want only the remainder, "as written on the ID", in full-width
digits — which cannot be re-derived reliably from `address.line1` / `line2`.

- `address.jp.{prefecture,city,town,chome,banchi,go,building,room}`
- `address.jp.postal_code_hyphenated` (`201-0001`)
- `address.jp.kana_remainder`

**Document metadata.** eKYC flows reject cards by issue date and need the card
number for the IC read, so this saves reopening the image every time. All three
are high sensitivity.

- `documents.<doc>.{number,issued_on,expires_on}` (ISO dates)
- `documents.<doc>.proves`: list of what the document evidences, e.g.
  `[name]` for 在留カード表面 and `[address]` for 裏面. Lets an agent pick the
  right file for "one document proving name, one proving address" instead of
  guessing from the label.

**Bank and payout accounts.** Use an array so multiple accounts coexist; always
high sensitivity.

- `bank.accounts[].{bank_name,account_name,account_number,branch_code,swift,clearing_code,currency,country,label}`

Prefer `bank.*` over a new top-level section — the redaction rules and the
confirmation gate already key off that prefix.

## Original Document Images (Attachments)

Some forms need the original image, not extracted text: residence card photos for KYC, bank card photos for payroll, My Number card scans. Keep these originals next to the profile so they sync with it and survive temp-file cleanup:

```bash
python3 scripts/profile_use.py attach /tmp/dl/img1.jpg --doc residence_card_front --label "在留カード 表面" --source "lark chat 2026-06-12" --move
python3 scripts/profile_use.py attachments --profile personal
python3 scripts/profile_use.py attachment-path --doc residence_card_front
python3 scripts/profile_use.py detach --doc residence_card_front
```

Files land in `<profile-dir>/attachments/<profile>/<doc>.<ext>` with mode 600; metadata (file, label, source, added date, sha256) is recorded under `documents.<doc>` in the profile JSON. This metadata is treated as high sensitivity — masked in `show`/`get` and excluded from the no-field `values` dump — because `label`/`source` often carry context (counterparty names, dates) you don't want in a redacted summary.

Conventional doc keys: `residence_card_front`, `residence_card_back`, `my_number_card_front`, `my_number_card_back`, `bank_card`, `passport_photo_page`, `health_insurance_card`, `drivers_license_front`. Free-form keys are fine (lowercase letters, digits, `_`, `-`, `.`).

Rules for originals:

1. When a document image appears in a chat download or temp directory and is worth keeping, `attach --move` it immediately, then delete any remaining temp copies. Do not leave ID images in `/tmp`, downloads, or the repo.
2. Treat every attachment as high sensitivity. Uploading an attachment to a website requires the user's explicit confirmation for that specific upload, even if autofill of text fields was already approved.
3. Use `attachment-path` to get the file path for an upload widget; never re-screenshot or copy the image elsewhere.
4. Do not attach one-time documents (CAPTCHAs, QR codes, temporary passes). Attach stable identity/payment documents only.
5. Expired or surrendered documents: `detach` them, or replace with `attach --force` when a renewed card arrives.

## Login Credentials (Bitwarden / Vaultwarden)

Account passwords do **not** live in the profile JSON. They stay in the user's password manager and are read live through `rbw` (a Bitwarden-compatible CLI that also talks to self-hosted Vaultwarden). The skill reads one credential at the moment of fill and never copies it into the profile, memory, logs, or chat.

### Setup is agent-driven — the user only types the master password

Do not hand the user a list of shell commands. When a credential is needed, the agent runs setup itself and stops only at the one step it must never perform (the master-password unlock).

1. Run `vault-status`. If `rbw_installed` is false or `unlocked` is false, set it up — don't ask the user to.
2. Install + configure in one command (the agent runs this):

   ```bash
   python3 scripts/profile_use.py vault-setup --install --base-url <server-url> --email <account-email>
   ```

   `--install` installs rbw via brew/cargo if missing. Get the server URL from the user (or a value they gave earlier, e.g. `https://bit.leeguoo.com`) and the email from `contact.email` if present; ask only for whatever is genuinely unknown.
3. `vault-setup` reports `next_step`. If it says to run `rbw login`, ask the user to run **that one command themselves** (in the `!` prompt or their terminal) and type their master password. The agent never asks for, runs with, captures, or echoes the master password. Once `rbw-agent` holds the unlock, every later `login` call just works.

After setup, use:

```bash
python3 scripts/profile_use.py vault-status                       # rbw installed? server? unlocked? (no secrets)
python3 scripts/profile_use.py login --domain example.com         # redacted: user t***@x.com / password ********
python3 scripts/profile_use.py login --domain example.com --reveal  # raw user + password — only at the moment of filling
python3 scripts/profile_use.py login --name "GitHub" --user me@x.com  # target an item directly / pick one account
python3 scripts/profile_use.py login --domain example.com --deep   # no name match? scan stored URIs (slower)
```

Matching is by **domain**: the form's host (e.g. `example.com`) is matched against vault item names, including the bare second-level label (`example`). When several items match, the command lists masked candidates and asks you to disambiguate with `--name`/`--user` — it does **not** fetch any password until exactly one item is chosen.

Rules for credentials:

1. Treat every credential as high sensitivity, like `payment`/`bank`. Default to the redacted output; fetch `--reveal` only at the instant you fill the field, and never paste the raw password into a final response.
2. Do not store, cache, or write credentials anywhere — not the profile JSON, not memory, not a temp file. Re-read from the vault each time.
3. The vault unlock belongs to `rbw-agent`. Never ask for, capture, store, or echo the master password. If `vault-status` shows `unlocked: false`, ask the user to run `rbw unlock` themselves.
4. Verify the real domain before filling a password, exactly as for any autofill. Stop on suspicious or typosquatted hosts.
5. Submitting a login/registration form still requires the user's explicit submit approval.

## Sync Guidance

Read `references/sync-model.md` when choosing or explaining where profile data should live.

Default recommendation:

- Use iCloud Drive for a single user's private plaintext profile on Apple devices.
- Use a password manager for payment cards, bank accounts, passwords, and one-time codes.
- Use GitHub only for the public skill code, profile schema, examples, or encrypted profile backups. Never put plaintext personal data in a public repository.

## Output Rules

- Final answers should say what was filled and what remains, using redacted values.
- Do not paste full card numbers, bank accounts, government IDs, or addresses into final responses unless the user explicitly asked to display them.
- If a profile file was created, report its local path and remind the user it contains placeholders until they edit it.

