terrylica/cc-skills/dashboard-forge
Claude Code and agent skill by terrylica/cc-skills
- community
Checking that the SKILL.md file is still in the repository.
Supervised browser automation of vendor dashboards and admin consoles for operations that have NO public API — minting scoped API tokens, creating OAuth apps, flipping account-level toggles, console-only settings. The method skill of web-forge, the one harness for this - recipes as data run by the web-forge CLI (idempotent ensure, read-back, a screenshot per step, a login gate that never types a credential) or node forge scripts; two connection modes (a signed-in profile of your everyday Chrome through the Playwright Extension, or a persistent per-site profile over CDP where a human logs in once); secrets extracted DOM-to-vault without ever being exposed; UI drift survived via the step-and-shoot method and a dated Vendor Quirks log. Use when a task needs a dashboard click-path (Cloudflare token/Zero Trust, GitHub OAuth apps, any admin console) and the vendor offers no API or your token lacks the scope to grant itself more. Triggers - "no API for this", "create an OAuth app", "mint a token in the dashboard", "automate the admin console", "browser-automate the setup", "write a console recipe".
Install
npx vskill@latest install terrylica/cc-skills/dashboard-forgeSKILL.md
dashboard-forge — supervised dashboard automation doctrine
Some operations exist ONLY behind a vendor's web UI (GitHub fine-grained PATs and OAuth apps have no creation API; a Cloudflare token cannot grant itself new scopes). This skill is the canonical method for automating those click-paths safely: the human supervises and handles logins/2FA; the scripts do everything else, reproducibly.
Harness (SSoT): this plugin, in two forms on shared foundations (plugin CLAUDE.md has the file map):
- Recipes — `scripts/web-forge.ts` (Bun): the step-and-shoot method as a CLI. A recipe is data (flags or a
--specJSON file → form operations), with idempotent ensure, read-back from a fresh load, a screenshot per step, a login gate that never types a credential, andDriver.extractToVaultfor reveals. Write new console automation as a recipe. Worked family: admin-console (Google Admin).bun "$(cc-plugin-root web-forge)/scripts/web-forge.ts" recipes --jsonlists every recipe, flag and exit code. - Forge scripts — `lib/browser-forge.mjs` (node ONLY: Bun's
connectOverCDPtimes out; needsplaywright-core, pinned at the repo root): Playwright held directly over CDP, for flows a recipe does not cover yet — token capture off the wire (captureBearer), consent dismissal, exact-name clicks. The cf-access-wall and azure-provision scripts use it.
Both take their browser from `lib/forge-chrome.mjs` and their secret sink from `lib/vault.mjs`.
Route choice — the two connection modes. If the session you need is already signed in to a profile of your everyday Chrome, use extension mode (recipes: --connect extension, the default): `chrome-profiles` (chrome-profile.sh setup <email>, zero clicks). For a supervised flow that wants its own isolated, persistent profile, use cdp mode (recipes: --connect cdp --site <name>; forge scripts: launchChrome(site)). Route ladder and Chrome-136 mechanics: chrome-profiles is the SSoT.
Self-Evolving Skill: dashboards drift constantly. When a selector misses or a flow changes, fix the recipe or forge script AND append the drift note to the Vendor Quirks section below — immediately, not later. Only update for real, reproducible breakage.
The method — step-and-shoot
Write the forge as small, resumable steps against a LONG-LIVED Chrome (launch once; each step connects, acts, disconnects — browser.close() on a CDP connection only detaches, Chrome keeps running). Never author one monolithic script against an unseen UI.
- Launch + human login.
launchChrome(site, loginUrl)(a recipe: its family's login gate); the human signs in (incl. 2FA). Detect completion withwaitForLogin(ctx, probeUrl, ok)— poll an authenticated endpoint viactx.requestwith the context cookies. NEVER navigate a visible tab to poll: you would reload a half-typed login form. - Identity preflight. Before ANY mutating step, extract the signed-in identity (a meta tag, a settings-page marker, an API echo) and
assertIdentity(actual, expected, resource). An account-owned resource created under the wrong login is a silent disaster (it happened: an OAuth app landed under the wrong GitHub user mid-forge because the human switched accounts). - Act in small steps, screenshot between. One interaction cluster per step;
shot(page, name)after each. When a locator misses, READ the latest shot, adapt, re-run just that step. Prefer role/label-based locators (getByRole, description-text anchoring) over CSS classes; for checkbox grids,page.evaluatewalking from a UNIQUE description text up to its row is far more drift-proof than nth-child chains. - Expect interceptors. Cookie/consent overlays (OneTrust & co.) swallow clicks and produce pure timeouts with no visible cause — call
dismissConsent(page)when a click times out mysteriously, then retry. GitHub-style sudo/2FA walls mid-flow: pause and let the supervising human clear them (or see gh-fine-grained-pat'sautosudo.mjsfor the autonomous passkey path). - Extract secrets DOM-only. On a token/secret reveal page:
page.evaluate→ match the value →vaultSet(scope, path, value)(a recipe:Driver.extractToVault, which never shoots and logs only the length). NEVER screenshot a reveal page — an agent reading that screenshot puts the secret into the conversation context permanently. If a reveal was accidentally captured, purge the file AND treat the secret as context-exposed (rotate if the transcript leaves the machine). - End-of-run hygiene.
purgeShots()(breadcrumbs can show near-secret state), thenteardown(site)— shuts down through chrome-profiles' port script (exact port flag), neverpkill -f(process-storm policy,~/.claude/CLAUDE.md).
Hybrid rule — forge the key, then use the door
Browser-automate the MINIMUM: usually just (a) the login and (b) the one form that mints a scoped credential. Everything after that goes through the vendor's REAL API with the minted credential, written as an idempotent GET-before-POST bootstrap (see the cf-access-wall skill for the worked template). UI automation is the crowbar, not the workflow.
Borrowed-session mode — driving a browser the HUMAN already logged into
A third mode, distinct from launching a per-site profile over CDP. Instead of owning a session, you borrow one that is already open in the operator's own Chrome and drive it via AppleScript:
Requires View → Developer → Allow JavaScript from Apple Events (persisted per profile as browser.allow_javascript_apple_events in Preferences — grep it to check before promising anything). You then have full DOM read/write with no driver, no profile copy, and no port.
When it is the RIGHT tool: the console is behind a passkey / hardware-key / step-up flow that you must not automate, and a human session already exists. You never touch the credential — you type inside a door somebody else opened. That distinction is the whole justification, and it is worth stating out loud in whatever you write afterwards.
When it is the WRONG tool: anything unattended, anything needing isolation, anything that should not be able to see the operator's other tabs. It has no sandbox by construction.
Hard-won rules, each one paid for:
- Address tabs by URL, never by index.
activateandset indexREORDER windows, so an index captured a moment ago can point somewhere else by the time you use it. Re-resolve on every call. Make the URL needle specific —"admin.google.com"will happily match a different admin tab and you will read the wrong page and believe it. - Read the JS from a FILE (
set js to read POSIX file "/tmp/step.js" as «class utf8»). Interpolating JS through bash → osascript → AppleScript string literals mangles quotes and backslashes in ways that fail silently or, worse, alter the script. - `offsetParent` is null for `position: fixed`, which is how essentially every Material/modal dialog is rendered. A "is it visible" filter built on
offsetParent !== nulltherefore hides the dialog you are looking for and you conclude the form never opened. UsegetBoundingClientRect()width/height instead. - Framework inputs need the NATIVE setter. Assigning
el.valueupdates the DOM but leaves Angular/React/Closure's model stale, so the form submits empty. UseObject.getOwnPropertyDescriptor(HTMLInputElement.prototype,'value').set.call(el, v)then dispatchinput+change(+blur). Read the value back and assert it. - Verify what is under the point before any coordinate-based click —
document.elementFromPoint(x,y)and compare to the intended element. In an admin console a mis-aimed click is not a failed test, it is an unintended action. - Chrome can be RUNNING with zero windows and refuse `open -a`.
make new windowvia Apple Events still works. Never quit or restart the operator's browser to "fix" it; you will destroy their tabs.
Secrets discipline (non-negotiable)
- Values ride PIPES:
vault set --stdin <scope> <path>(SCS vault). Never argv, never stdout, never a chat transcript. - Scripts print LENGTHS and vault paths, not values (
✓ vaulted (len 53)). - Profile dirs (
~/.local/share/web-forge/profile-<site>) hold live sessions — sensitive, never committed, listed in backups as credential-equivalent. - Public identifiers (OAuth client_id, account ids) may be logged; anything CONCEALED may not.
Vendor quirks (drift log — append, with dates)
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 75 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingplugins/web-forge/skills/dashboard-forge/SKILL.md
Popularity
- Repository stars
- 62
- Repository forks
- 10
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/terrylica/cc-skills/dashboard-forge)