Playwright Skill
tech-leads-club/agent-skills
Complete browser automation with Playwright. An agent skill from tech-leads-club/agent-skills.
A skill your agent uses whenever the user needs to log in to a website on their phone and reuse that authenticated session locally, especially for Playwright storageState JSON, cookies/localStorage…
$ npx skills add Lakr233/Cookey --skill website-login -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Lakr233/Cookey website-login --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Lakr233/Cookey.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/website-login .claude/skills/website-login && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "website-login" agent skill from https://github.com/Lakr233/Cookey/tree/main/skills/website-login into .claude/skills/website-login/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "website-login", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Lakr233/Cookey/tree/main/skills/website-loginType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Lakr233/Cookey --skill website-login -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Lakr233/Cookey website-login --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Lakr233/Cookey.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/website-login .agents/skills/website-login && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "website-login" agent skill from https://github.com/Lakr233/Cookey/tree/main/skills/website-login into .agents/skills/website-login/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "website-login", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Lakr233/Cookey --skill website-login -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Lakr233/Cookey website-login --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Lakr233/Cookey.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/website-login .cursor/skills/website-login && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "website-login" agent skill from https://github.com/Lakr233/Cookey/tree/main/skills/website-login into .cursor/skills/website-login/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "website-login", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Lakr233/Cookey.git --path skills/website-login--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Lakr233/Cookey --skill website-login -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Lakr233/Cookey website-login --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Lakr233/Cookey.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/website-login .gemini/skills/website-login && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "website-login" agent skill from https://github.com/Lakr233/Cookey/tree/main/skills/website-login into .gemini/skills/website-login/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "website-login", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Lakr233/Cookey website-loginInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Lakr233/Cookey --skill website-login -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Lakr233/Cookey.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/website-login .github/skills/website-login && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "website-login" agent skill from https://github.com/Lakr233/Cookey/tree/main/skills/website-login into .github/skills/website-login/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "website-login", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Lakr233/Cookey --skill website-login -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Lakr233/Cookey website-login --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Lakr233/Cookey.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/website-login .opencode/skills/website-login && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "website-login" agent skill from https://github.com/Lakr233/Cookey/tree/main/skills/website-login into .opencode/skills/website-login/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "website-login", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
website-loginA skill your agent uses whenever the user needs to log in to a website on their phone and reuse that authenticated session locally, especially for Playwright storageState JSON, cookies/localStorage…
Website Login is an agent skill from Lakr233/Cookey. Use whenever the user needs to log in to a website on their phone and reuse that authenticated session locally, especially for Playwright storageState JSON, cookies/localStorage capture, MFA, SMS codes, passkeys, or mobile-first login flows that are awkward in headless automation. You run Cookey CLI in your current environment; the user signs in on their iPhone in the Cookey app; the relay only transports encrypted blobs. Trigger even if the user asks more loosely for help logging in, reusing an authenticated…
Its SKILL.md is about 3.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Testing & QA, covering Browser testing, Responsive design and Authentication. It works with Playwright. The licence is MIT.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 86de969. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npmpipFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
api.cookey.shgithub.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Website Login loads about 3.7k tokens when it runs. Until then it costs about 155 tokens; SKILL.md has 1,785 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Lakr233/Cookey at commit 86de969, republished under its MIT licence (© Lakr233). 1,785 words, ~3,699 tokens.
.claude/skills/website-login/SKILL.md (or your agent's skills folder).You run the Cookey CLI in your current environment. The user completes the actual website login on their iPhone inside the Cookey app’s in-app browser—never on a browser you control remotely.
Cookey splits “where login happens” from “where automation runs”:
Local environment (cookey CLI + local daemon) — You run commands here. The CLI creates a short-lived login request, agrees cryptographic keys with the phone, and waits for an encrypted payload. After delivery, you export Playwright-compatible storageState JSON (cookies + origins / localStorage) for local scripts.
User’s iPhone (Cookey app) — The user scans the QR or taps the HTTPS jump link. The jump page opens the cookey:// deep link into the app. The app opens the target URL in its embedded browser. The user signs in like a normal mobile session (password, OTP, authenticator app, passkeys, etc.). The app reads cookies and storage, encrypts them, and uploads ciphertext to the relay.
Relay server — Only moves opaque encrypted blobs and request metadata. It is not trusted with plaintext cookies or credentials; design assumes zero-knowledge transport.
Result — The CLI decrypts locally and writes session material under ~/.cookey/. cookey session export strips Cookey-only metadata and outputs the same shape Playwright expects for browser.newContext({ storageState }).
Why use this: Many real sites are easier or only possible to log into on a phone (MFA apps, SMS, mobile-only UI). Cookey turns that authenticated mobile browser state into something local Playwright can load.
npm install -g @cookey/cli
# or
pip install cookeyAlternatively, download prebuilt binaries:
cookey session export writes standard Playwright storageState JSON:
cookiesoriginsCookey keeps extra local metadata under ~/.cookey/; session export strips
that and emits only what Playwright consumes.
You start a login request in your local environment:
cookey request start https://example.com/login --json --qr
The user scans the QR (or opens the link) on their iPhone with the Cookey app, then finishes login in the app’s browser.
You export after the session is delivered:
cookey session export --latest --out storageState.json --pretty
You (or the user’s code) load it in Playwright:
import { chromium } from "@playwright/test";
const browser = await chromium.launch();
const context = await browser.newContext({
storageState: "storageState.json",
});
const page = await context.newPage();
await page.goto("https://example.com/account");You can also pipe to a file:
cookey session export r_xxxxxxxxxxxxxxxxxxxxxx > storageState.json
When you start or refresh a request for the user, follow this order:
cookey request start ... --json --qr or cookey request refresh ... --json --qr without --attach.cookey request status <rid> --watch or poll until the request is ready.cookey session export.If you skip step 2 and start waiting first, the user may never see the pair key in tool-call environments where terminal output is hidden.
When you start or refresh a Cookey request for the user, paste the required values from the CLI into your reply before you wait for completion. Do not only mention that a login request was started.
jump_link as a clickable HTTPS link.--qr or --json --qr, always wrap the ASCII QR code in a text ... code block to prevent Markdown from destroying the line breaks. If using --json, the QR code is in the qr_text field with \n characters.cookey:// deep link as the primary user action; many chat surfaces will not expose it as a tappable link.jump_link is not enough by itself; still include the pair key and fingerprint alongside it.--json, copy pair_key, cli_public_key_fingerprint, jump_link, and qr_text from the JSON output exactly.The Cookey app on the user’s iPhone may ask them to type the pair key and confirm the fingerprint matches the terminal.
Use a reply shape like this:
ABCD-1234xxxxxxhttps://...<ascii qr code>--attachUnless your tool-call environment keeps a detached process alive (e.g. nohup
or similar), do not use --attach. If the parent exits, verification can expire.
Default is detached: cookey request start / cookey request refresh spawns a background daemon and returns once the local descriptor exists. --attach blocks in the foreground until the session arrives.
For agent or tool-call environments where the user cannot directly inspect stdout, treat --attach as unsafe by default even if it technically works. It makes it too easy to block before you have echoed the pair key and fingerprint back to the user.
cookey request start <target_url>Create a new login request for target_url, register it with the relay, print
the pair key / jump link, and start a local waiter process.
Flags:
--server URL override the relay server; must be https://--timeout SECONDS request lifetime in seconds; default 300, capped at 1800--qr render the cookey:// deep link as a terminal QR code--json emit machine-readable JSON instead of human-readable output--attach wait inline instead of launching a detached daemon--help print command usageExamples:
cookey request start https://example.com/logincookey request start https://example.com/login --qrcookey request start https://example.com/login --json --qrcookey request start https://example.com/login --timeout 900 --server https://api.cookey.shcookey request start https://example.com/login --jsonNotes:
rid), pair key, jump link, and
daemon PID. It also prints the CLI fingerprint / verification string when
available.--attach, the command exits as soon as the detached daemon is ready
to wait for the encrypted session.--json --qr, send the returned pair key / fingerprint / QR code to the user immediately, then watch status in a separate step.cookey request refresh <target_url>Create a refresh request for target_url using the latest local session for the
same target as seed state.
Flags:
cookey request startExamples:
cookey request refresh https://example.com/logincookey request refresh https://example.com/login --qrcookey request refresh https://example.com/login --json --qrcookey request refresh https://example.com/login --attachNotes:
no previous session found for this target; run cookey request start firstcookey request status [rid]Inspect local request state. If there is no local record for the requested rid,
Cookey falls back to relay status using the configured default server.
Flags:
--latest inspect the most recently updated local request or session--watch poll once per second until a terminal state is reached--json emit machine-readable JSON--help print command usageExamples:
cookey request statuscookey request status r_xxxxxxxxxxxxxxxxxxxxxxcookey request status --latestcookey request status --latest --watchcookey request status r_xxxxxxxxxxxxxxxxxxxxxx --jsonStatus values:
waiting daemon is alive and waiting for the encrypted sessionreceiving session arrived and is being decrypted / written locallyready session file exists and is exportableexpired request lifetime ended before a usable session was writtenorphaned daemon descriptor says the request was active, but the daemon process is goneerror the daemon failed while waiting, decrypting, or writingmissing no local or remote record was foundNotes:
cookey request status with no rid and no --latest returns a summary of
the latest daemon and latest session.--watch requires either an explicit rid or --latest.cookey session export [rid]Export a local session as Playwright storageState JSON.
Flags:
--latest export the newest local session--out FILE write to FILE instead of stdout--pretty pretty-print JSON with indentation--help print command usageExamples:
cookey session export --latest > storageState.jsoncookey session export --latest --out storageState.json --prettycookey session export r_xxxxxxxxxxxxxxxxxxxxxxNotes:
--out is relative, it is resolved against the current working directory.expired from error.browser.newContext({ storageState }).cookey session listList all locally known request IDs, newest first, using the newest timestamp from either the daemon descriptor or the exported session file.
Flags:
--json emit machine-readable JSON--help print command usageExamples:
cookey session listcookey session list --jsoncookey session delete <rid>Delete the local session file and daemon descriptor for rid.
Flags:
--json emit machine-readable JSON--help print command usageExamples:
cookey session delete r_xxxxxxxxxxxxxxxxxxxxxxcookey session delete r_xxxxxxxxxxxxxxxxxxxxxx --jsonNotes:
waiting
or receiving state.cookey session cleanDelete all inactive local request/session pairs.
Flags:
--json emit machine-readable JSON--help print command usageExamples:
cookey session cleancookey session clean --jsonNotes:
cookey config get [key]Read configured defaults from ~/.cookey/config.json.
Supported keys:
default-servertimeout-secondssession-retention-daysAliases:
server -> default-servertimeout -> timeout-secondsretention-days -> session-retention-daysFlags:
--json emit machine-readable JSON--help print command usageExamples:
cookey config getcookey config get default-servercookey config get timeout --jsoncookey config set <key> <value>Persist configured defaults in ~/.cookey/config.json.
Flags:
--json emit machine-readable JSON--help print command usageExamples:
cookey config set default-server https://api.cookey.shcookey config set timeout-seconds 900cookey config set retention-days 30 --jsonNotes:
default-server must parse as a relay base URL and must use https.timeout-seconds must be a positive integer.session-retention-days is stored in config today, but the current CLI does
not automatically delete sessions based on that value. Use session clean for
explicit cleanup.~/.cookey/, ensures the keypair exists,
ensures device ID exists, and cleans up stale daemon descriptors.~/.cookey/ is written atomically.0 on success and 1 on CLI/validation errors.--attach can also return:3 when the request expires before session delivery5 when the daemon encounters a relay, decrypt, or local write failureDetached start + watch:
cookey request start https://example.com/login --qr
cookey request status --latest --watch
cookey session export --latest --out storageState.json --prettyJSON-first scripting (Note: If you need to show the QR code to the user while using JSON output, use --json --qr and extract the qr_text field, formatting it carefully inside a ```text block):
cookey request start https://github.com/login --json --qr
cookey request status --latest --json
cookey session export --latest --out storageState.json(Tip: When testing the login flow, avoid stateless domains like example.com which will yield an empty session. Use a real site like github.com/login or x.com/login to verify cookies and localStorage are captured correctly.)
Playwright usage:
import { chromium } from "@playwright/test";
const browser = await chromium.launch();
const context = await browser.newContext({
storageState: "storageState.json",
});© Lakr233, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/website-login of Lakr233/Cookey.
Open the folder on GitHubat commit 86de969
Website Login next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Website Login this skillLakr233/Cookey | 160 | — | ~3.7k | Automated safety check: Pass | MIT | |
| Playwright Skilltech-leads-club/agent-skills | 7k | — | ~3.6k | Automated safety check: Pass | Custom licence | |
| Playwright Skilllackeyjb/playwright-skill | 3.2k | — | ~1.9k | Automated safety check: Pass | MIT | |
| Playwright Coretestdino-hq/playwright-skill | 390 | 1 repos | ~1.4k | Automated safety check: Pass | MIT | |
| Playwright Login Flowsandrewyng/context-hub | 14k | — | ~715 | Automated safety check: Pass | MIT | |
| Open BrowserJasonHonKL/Openbrowser | 114 | — | ~1.6k | Automated safety check: Pass | MIT |
tech-leads-club/agent-skills
Complete browser automation with Playwright. An agent skill from tech-leads-club/agent-skills.
lackeyjb/playwright-skill
Complete browser automation with Playwright. An agent skill from lackeyjb/playwright-skill.
testdino-hq/playwright-skill
Battle-tested Playwright patterns for writing and debugging reliable E2E, API, component, visual, accessibility, and security tests.
andrewyng/context-hub
Collects reusable Playwright patterns for logging in during end-to-end tests: password forms, OAuth redirects, saved browser state and TOTP two-factor codes.
JasonHonKL/Openbrowser
A skill your agent uses whenever the task involves browsing web pages, extracting page content, clicking forms, or completing web workflows.
petrkindlmann/qa-skills
Test REST and GraphQL APIs with Playwright APIRequestContext, Supertest, or standalone HTTP clients.
Works with
Categories
A skill your agent uses whenever the user needs to log in to a website on their phone and reuse that authenticated session locally, especially for Playwright storageState JSON, cookies/localStorage…. Website Login is an agent skill from Lakr233/Cookey. Use whenever the user needs to log in to a website on their phone and reuse that authenticated session locally, especially for Playwright storageState JSON, cookies/localStorage capture, MFA, SMS codes, passkeys, or mobile-first login flows that are awkward in headless automation.
Website Login fits situations like: the user needs to log in to a website on their phone and reuse that authenticated session locally; especially for Playwright storageState JSON; cookies/localStorage capture; mobile-first login flows that are awkward in headless automation.
Run `npx skills add Lakr233/Cookey --skill website-login -a claude-code`. Or copy the skill folder (skills/website-login in Lakr233/Cookey) into .claude/skills/website-login in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Lakr233/Cookey --skill website-login -a codex`. Or copy the skill folder (skills/website-login in Lakr233/Cookey) into .agents/skills/website-login in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Lakr233/Cookey --skill website-login -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/website-login, .gemini/skills/website-login, .github/skills/website-login and .opencode/skills/website-login in your project.
Going by SKILL.md and its folder, Website Login needs the command-line tools its instructions call (npm and pip). Our summary lists: Python 3; Node.js.
SKILL.md names 2 domains. In commands or code: api.cookey.sh and github.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Website Login is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.7k tokens (SKILL.md is roughly 15k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Website Login: Playwright Skill (tech-leads-club/agent-skills, 7k stars), Playwright Skill (lackeyjb/playwright-skill, 3.2k stars), Playwright Core (testdino-hq/playwright-skill, 390 stars) and Playwright Login Flows (andrewyng/context-hub, 14k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Lakr233 (a GitHub user) maintains it in Lakr233/Cookey, which has 160 GitHub stars. The repository was last updated on June 1, 2026.
Source: Lakr233/Cookey on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.