REQUIRED before any typed web step that needs a login, card, OTP, or other private value the user types, and before request_box_help for those steps; send RequestUserForm for the fields, embedded card frames included, and hand off only after the host refuses or a fill fails. Ask in chat for names, addresses, phones, emails, and preferences, except a shipping address for an order card checkout, which the `purchases` skill collects with a contact form.
Installs into .claude/skills of the current project.
Are you the author of In Chat Forms?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/danielfebrero-in-chat-forms)
---
name: in-chat-forms
description: >-
REQUIRED before any typed web step that needs a login, card, OTP, or other
private value the user types, and before request_box_help for those steps;
send RequestUserForm for the fields, embedded card frames included, and hand
off only after the host refuses or a fill fails. Ask in chat for names,
addresses, phones, emails, and preferences, except a shipping address for an
order card checkout, which the `purchases` skill collects with a contact form.
---
# In-chat forms for typed steps
When a page needs the USER to type a login (username and password) or card details (number, expiry, security code) that no saved login, connected password manager, or saved card fills, a one-time code you cannot read from a mailbox, or another private value such as an account PIN, an ID number, or a security answer, call RequestUserForm to show the Secure Form, a native in-chat form, instead of handing over the box and instead of asking them to paste it in chat. The host fills the live page with what they submit; every value is write-only and never comes back to you. The receipt reports only per-field fill status. For secret fields (password/otp/secret:true), that receipt IS the verification. Recover from a failed secret fill by re-asking with a new form (fresh target) or with request_box_help, and NEVER take a screenshot to check what landed in a secret field. Structured snapshots redact secret values, but a screenshot is raw page pixels and redacts nothing. Non-secret outcomes can be verified from the page itself (fresh snapshot) or re-asked. Keep request_box_help for steps a form cannot express: a captcha the subagent tried and could not get past, passkeys, 3DS confirmation prompts, QR codes, device approvals, and unusual custom widgets. Dispatch the subagent to attempt any captcha itself first, whether a checkbox, a puzzle, an image challenge, or a press-and-hold I'm-human button (holdDurationMs), rather than handing the box over.
- For a name, address, phone number, email, or preference a page asks for, ask in chat and type the answer in yourself, except a shipping address for an order card checkout, which the `purchases` skill collects with a contact form; the `vault` skill covers looking those up first and saving them.
- Hard rule: after the typed page is open, take a fresh snapshot. Call `RequestUserForm` whenever the login, card, code, or other private fields are on the page and each one has a target (ref/selector/label). Fields inside iframes (cross-origin ones included, such as a checkout's Shopify or Stripe card frame) and inside shadow roots count; the host reaches them. Using `request_box_help` for a typed field that has a usable target is wrong. A value the user already sent in chat needs no form: use it as the `sign-in` skill says. For a sign-up where the user lets you pick the password, follow the `sign-in` skill instead of RequestUserForm.
- Never predict a fill failure up front, and never offer the form "as a test". Go straight to `request_box_help` only for steps a form cannot express (a captcha the subagent tried and could not get past, slider and drag-to-verify captchas included, passkey, 3DS, QR code, device approval, a custom widget that is not a captcha) or when the page has no field to target. A host preflight refusal, or a receipt naming a structural reason (closed shadow root, unreachable frame), is final for that page: hand off with `request_box_help`, quote the receipt's reason to the user as written (do not rename it, e.g. as a "protected" or "secure" frame), and do not re-issue the same form. Any other miss follows the receipt: remap a held value or re-ask with a fresh target.
- A special-cased site (United, Okta, etc.) does **not** change this. Still snapshot, then send the form, after the page is open.
- If the form asks only for a 2FA or one-time code, send the Secure Form with no explanation. Otherwise, tell the user in one line that secret values such as passwords are stored encrypted and filled into the page only when you need them, and that you never see them.
- Sign in with the Cursor-managed `sign-in` skill, in its order: saved logins first, then any connected password manager, and only then the Secure Form or handing over the screen. One-time codes and captchas follow the rules in that skill.
- Note: the in-chat form card may not render on mobile; if the user says they can't see it, say so plainly and offer desktop chat or `request_box_help` as the fallback.
- Reach for the form the moment you hit the typed gate. Never pre-ask "want me to hand you the box?" or "should I show you a form?" The form (or the handoff) IS the ask.
- Give every field a target from the CURRENT page and pass the destination domain from the browser bar, which stays the top page's domain even when the fields are embedded from another site. A target is an [ref=eN] from the latest browser snapshot, a CSS selector, or the field's visible label, and a browser subagent's report includes the [ref=eN] values. Snapshots and fill targets pierce shadow roots and iframes, including cross-origin ones such as a checkout's embedded card fields from Shopify, Stripe, or another payment provider, so those fields resolve like any other. A frame that is still loading is not a reason to skip the form: take a fresh snapshot once it has loaded, then send the form. Ask for card number, expiry, and security code as separate fields, each targeting its own input, never the frame; selectors may use the '>>>' combinator to re-root inside a shadow host. Never predict that a form cannot reach fields because they are embedded, iframed, served from another site, or inside a custom element. Send the form and let the host's preflight and fill decide. If there is nothing to point a target at yet (no snapshot, the page is unclear), take a fresh snapshot first.
- The host preflights every targeted field against the live page BEFORE showing the card. A refusal saying the targets are structurally unreachable is FINAL for that page. The user was never asked to type, and another form into the same place will be refused the same way, so call request_box_help. The same goes for a receipt or dropped-field note naming those reasons after a fill. Only such a refusal or receipt ends the form attempt; your own read of the page never does. When you hand off after one, tell the user in one sentence which field failed and quote the reason the host gave as written, without renaming it or adding a guess.
- By default the host only fills values; it never clicks the site's own sign-in/continue button on its own. After you're resumed with the receipt, take a fresh page SNAPSHOT first, then click the submit control yourself (via the browser subagent). Never assume the page moved on, and don't reach for a screenshot while a submitted secret could still be visible on the page.
- For a one-shot code step, meaning an OTP or verification-code prompt whose only action is entering the code and submitting, set submitAfterFill: true so the host presses Enter right after filling. Codes expire, and the extra resume round-trip can cost the step. The host enforces that scope: the form must claim a domain and carry exactly ONE targeted single-line text field, the card tells the user it will submit, and the Enter press runs only when every fill landed. Leave it off for logins, checkout, and anything where submitting has side effects you should verify first; the receipt tells you whether the submit was attempted and succeeded.
- When a receipt says the host still HOLDS a missed field's value and offers a remap, the user is not asked again: in that same turn, find the field's new target in the fresh snapshot on the receipt and call the first-party RemapUserFormTargets tool through CallDynamicTool (namespace "cursor") with each fieldId mapped to its new target (all held fields in one call). The host writes the value they already typed; you never see or supply one. Only if the field is truly gone from the page do you skip it, and even then you continue from the page or hand over the screen rather than re-asking.
- If the user dismisses the form, treat it as declined and don't immediately re-issue the same form. If they choose to do it on the screen instead, the host hands them the box directly and resumes you when they hand it back, the same as request_box_help, with nothing for you to do in between.