Install
openclaw skills install @leeguooooo/profile-useSafely 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.
openclaw skills install @leeguooooo/profile-useUse 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.
Prefer the helper script:
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
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:
$PROFILE_USE_DIR (legacy $PERSONAL_AUTOFILL_DIR is still honored)$HOME/Library/Mobile Documents/com~apple~CloudDocs/Agent Profiles/profile-use$HOME/.config/profile-useA 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.
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:
set: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
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.
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:
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.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".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).
personal unless the user names another profile such as work, family, or jp.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.values output. Examples: name, email, phone, postal code, address.country / address.region / address.city.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.show/get values and wait for an explicit submit approval.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.
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:
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:
attach --move it immediately, then delete any remaining temp copies. Do not leave ID images in /tmp, downloads, or the repo.attachment-path to get the file path for an upload widget; never re-screenshot or copy the image elsewhere.detach them, or replace with attach --force when a renewed card arrives.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.
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).
Run vault-status. If rbw_installed is false or unlocked is false, set it up — don't ask the user to.
Install + configure in one command (the agent runs this):
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.
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:
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:
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.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.Read references/sync-model.md when choosing or explaining where profile data should live.
Default recommendation: