Phone Harness
ShawnPana/phone-harness
Control the user's phone — an iPhone through the Mac's iPhone Mirroring window, an Android over adb, or a rented cloud Android: open apps, tap, type, swipe, read the screen.
UI verification workflow — open modals, query DOM contract selectors, interact with inputs, take screenshots, and validate UI rendering via the operability facade.
$ npx skills add saberzero1/quartz-syncer --skill verify-ui -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install saberzero1/quartz-syncer verify-ui --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/saberzero1/quartz-syncer.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/verify-ui .claude/skills/verify-ui && 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 "verify-ui" agent skill from https://github.com/saberzero1/quartz-syncer/tree/main/.agents/skills/verify-ui into .claude/skills/verify-ui/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "verify-ui", 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/saberzero1/quartz-syncer/tree/main/.agents/skills/verify-uiType 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 saberzero1/quartz-syncer --skill verify-ui -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install saberzero1/quartz-syncer verify-ui --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/saberzero1/quartz-syncer.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/verify-ui .agents/skills/verify-ui && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "verify-ui" agent skill from https://github.com/saberzero1/quartz-syncer/tree/main/.agents/skills/verify-ui into .agents/skills/verify-ui/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "verify-ui", 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 saberzero1/quartz-syncer --skill verify-ui -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install saberzero1/quartz-syncer verify-ui --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/saberzero1/quartz-syncer.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/verify-ui .cursor/skills/verify-ui && 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 "verify-ui" agent skill from https://github.com/saberzero1/quartz-syncer/tree/main/.agents/skills/verify-ui into .cursor/skills/verify-ui/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "verify-ui", 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/saberzero1/quartz-syncer.git --path .agents/skills/verify-ui--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 saberzero1/quartz-syncer --skill verify-ui -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install saberzero1/quartz-syncer verify-ui --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/saberzero1/quartz-syncer.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/verify-ui .gemini/skills/verify-ui && 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 "verify-ui" agent skill from https://github.com/saberzero1/quartz-syncer/tree/main/.agents/skills/verify-ui into .gemini/skills/verify-ui/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "verify-ui", 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 saberzero1/quartz-syncer verify-uiInstalls 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 saberzero1/quartz-syncer --skill verify-ui -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/saberzero1/quartz-syncer.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/verify-ui .github/skills/verify-ui && 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 "verify-ui" agent skill from https://github.com/saberzero1/quartz-syncer/tree/main/.agents/skills/verify-ui into .github/skills/verify-ui/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "verify-ui", 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 saberzero1/quartz-syncer --skill verify-ui -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install saberzero1/quartz-syncer verify-ui --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/saberzero1/quartz-syncer.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/verify-ui .opencode/skills/verify-ui && 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 "verify-ui" agent skill from https://github.com/saberzero1/quartz-syncer/tree/main/.agents/skills/verify-ui into .opencode/skills/verify-ui/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "verify-ui", 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.
verify-uiUI verification workflow — open modals, query DOM contract selectors, interact with inputs, take screenshots, and validate UI rendering via the operability facade.
Verify UI is an agent skill from saberzero1/quartz-syncer. UI verification workflow — open modals, query DOM contract selectors, interact with inputs, take screenshots, and validate UI rendering via the operability facade.
Its SKILL.md is about 2.3k 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 Mobile, covering Mobile testing and debugging. It works with Obsidian. The repository describes itself as: Manage and publish your notes to Quartz, the fast, batteries-included static-site generator. The licence is MIT.
Read from SKILL.md and the folder at commit 8f04c08. 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:
npmFrom 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:
github.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.
Verify UI loads about 2.3k tokens when it runs. Until then it costs about 43 tokens; SKILL.md has 543 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 saberzero1/quartz-syncer at commit 8f04c08, republished under its MIT licence (© saberzero1). 543 words, ~2,278 tokens.
.claude/skills/verify-ui/SKILL.md (or your agent's skills folder).After modifying view code (PublicationCenter, OnboardingWizard, QuartzHub, DiffModal, StatusBar, settings), verify the UI renders correctly by querying DOM contract selectors, interacting with inputs, and taking screenshots.
npm run build:dev (copies to test vault, enables facade via __DEV__ flag).obsidian eval code="typeof window.__QS__" 2>/dev/null returns => object).obsidian dev:debug on 2>/dev/null (once per session).Activate when:
src/views/styles.css that affect plugin UISuppress CLI noise. Always append 2>/dev/null to every obsidian CLI command.
Async eval pattern. Use IIFE + console.log for async calls:
obsidian eval code="(async()=>{const r=await window.__QS__.act({name:'pub.open'});console.log(JSON.stringify(r))})()" 2>/dev/nullMissing eval output is not failure. obsidian eval only captures what is logged within ~5–15 ms. Modal-opening actions frequently outlast that — pub.open prints {"success":true} on a warm status and prints nothing on a cold tree. The DOM query that follows is the real check, which is why every workflow below pairs an action with a dev:dom assertion.
Setting input values. DOM .value assignment does NOT trigger event listeners. Always dispatch an input event:
obsidian eval code="const el=document.querySelector('[data-qs=\"hub-setup-clone-url\"]');el.value='https://example.com/repo.git';el.dispatchEvent(new Event('input',{bubbles:true}))" 2>/dev/nullWait after operations. Approximate wait times:
Verify actions took effect. After triggering an action, always query the DOM to confirm:
obsidian eval code="document.querySelector('[data-qs=\"hub-action\"][data-qs-value=\"build\"]')?.click()" 2>/dev/null
sleep 3 && obsidian dev:dom selector='.qs-terminal-output' total 2>/dev/nullStacked modals. When a modal opens another (e.g., Hub → Plugin Browser), close in reverse order:
# Close Plugin Browser first (topmost)
obsidian eval code="document.querySelector('.quartz-syncer-plugin-browser .modal-close-button')?.click()" 2>/dev/null
sleep 1
# Then close the Hub
obsidian eval code="(async()=>{const r=await window.__QS__.act({name:'hub.close'});console.log(JSON.stringify(r))})()" 2>/dev/nullTerminalOutputModal. Has no data-qs attributes. Close with:
obsidian eval code="document.querySelector('.qs-terminal-output .qs-terminal-output-actions button:last-child')?.click()" 2>/dev/nullAll queryable elements use data-qs attributes. Never use raw CSS classes for verification.
| Selector | Element |
|---|---|
[data-qs="pub-center"] | Publication center modal |
[data-qs="pub-row"] | File row (has data-qs-path) |
[data-qs="pub-checkbox"] | Checkbox (has data-qs-path or data-qs-category) |
[data-qs="pub-category"] | Category header (has data-qs-value) |
[data-qs="pub-tab"] | Tab button (has data-qs-value) |
[data-qs="pub-publish-btn"] | Publish button |
[data-qs="pub-delete-btn"] | Delete button |
[data-qs="pub-search"] | Filter input |
[data-qs="pub-progress"] | Progress bar |
[data-qs="wizard"] | Onboarding wizard |
[data-qs="wizard-step"] | Step indicator (has data-qs-value) |
[data-qs="wizard-next"] | Next/continue button |
[data-qs="wizard-input"] | Input field (has data-qs-field) |
[data-qs="wizard-error"] | Error display |
[data-qs="statusbar"] | Status bar (has data-qs-state) |
[data-qs="diff-view"] | Diff viewer |
[data-qs="hub"] | Quartz Hub modal |
[data-qs="hub-tab"] | Hub tab button (has data-qs-value) |
[data-qs="hub-status"] | Hub status panel |
[data-qs="hub-action"] | Hub action button (has data-qs-value) |
[data-qs="hub-setup-link-path"] | Hub setup link path input |
[data-qs="hub-setup-link"] | Hub setup link button |
[data-qs="hub-setup-clone-url"] | Hub setup clone URL input |
[data-qs="hub-setup-clone-dest"] | Hub setup clone destination input |
[data-qs="hub-setup-clone"] | Hub setup clone button |
obsidian eval code="(async()=>{const r=await window.__QS__.act({name:'pub.open'});console.log(JSON.stringify(r))})()" 2>/dev/null
sleep 2
obsidian dev:dom selector='[data-qs="pub-center"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="pub-row"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="pub-category"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="pub-publish-btn"]' text 2>/dev/null
obsidian dev:dom selector='[data-qs="pub-tab"]' total 2>/dev/null
obsidian dev:screenshot path=/tmp/pub-center.png 2>/dev/null
obsidian eval code="(async()=>{const r=await window.__QS__.act({name:'pub.close'});console.log(JSON.stringify(r))})()" 2>/dev/nullobsidian command id=quartz-syncer:open-hub 2>/dev/null
sleep 2
obsidian dev:dom selector='[data-qs="hub"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="hub-tab"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="hub-status"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="hub-action"]' total 2>/dev/null
obsidian dev:screenshot path=/tmp/hub.png 2>/dev/null
# Switch to Setup tab
obsidian eval code="document.querySelector('[data-qs=\"hub-tab\"][data-qs-value=\"setup\"]')?.click()" 2>/dev/null
sleep 1
obsidian dev:dom selector='[data-qs="hub-setup-link"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="hub-setup-clone"]' total 2>/dev/null
obsidian eval code="(async()=>{const r=await window.__QS__.act({name:'hub.close'});console.log(JSON.stringify(r))})()" 2>/dev/nullobsidian command id=quartz-syncer:open-hub 2>/dev/null
sleep 2
obsidian eval code="document.querySelector('[data-qs=\"hub-tab\"][data-qs-value=\"setup\"]')?.click()" 2>/dev/null
sleep 1
# Set path and trigger validation
obsidian eval code="const el=document.querySelector('[data-qs=\"hub-setup-link-path\"]');el.value='/path/to/quartz';el.dispatchEvent(new Event('input',{bubbles:true}))" 2>/dev/null
sleep 1
obsidian dev:screenshot path=/tmp/hub-link.png 2>/dev/null
# Check validation showed "Quartz repo detected" before clicking Link
obsidian eval code="document.querySelector('[data-qs=\"hub-setup-link\"]')?.click()" 2>/dev/nullobsidian eval code="(async()=>{const r=await window.__QS__.act({name:'hub.setup.clone',params:{url:'https://github.com/user/quartz.git',dest:'/path/to/dest',confirm:true}});console.log(JSON.stringify(r))})()" 2>/dev/nullobsidian command id=quartz-syncer:setup-wizard 2>/dev/null
sleep 2
obsidian dev:dom selector='[data-qs="wizard"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="wizard-step"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="wizard-input"]' total 2>/dev/null
obsidian dev:dom selector='[data-qs="wizard-next"]' text 2>/dev/null
obsidian dev:dom selector='[data-qs="wizard-error"]' total 2>/dev/null
obsidian dev:screenshot path=/tmp/wizard.png 2>/dev/nullobsidian dev:dom selector='[data-qs="statusbar"]' attr=data-qs-state 2>/dev/null[data-qs="..."] selectors — never raw CSS classes.2>/dev/null to all CLI commands.total) before querying content (text, attr).dispatchEvent after setting input .value..qs-terminal-output) which lacks data-qs.2>/dev/null — GTK warnings break output parsing.await in eval — use the IIFE pattern..value without dispatchEvent — event listeners won't fire.© saberzero1, 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 .agents/skills/verify-ui of saberzero1/quartz-syncer.
Open the folder on GitHubat commit 8f04c08
Verify UI 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 |
|---|---|---|---|---|---|---|
| Verify UI this skillsaberzero1/quartz-syncer | 140 | — | ~2.3k | Automated safety check: Pass | MIT | |
| Phone HarnessShawnPana/phone-harness | 3.2k | — | ~4.3k | Automated safety check: Pass | MIT | |
| Maa Issue Log AnalysisMaaAssistantArknights/MaaAssistantArknights | 24k | — | ~4k | Automated safety check: Pass | AGPL-3.0 | |
| Mobile QAtloncorp/tlon-apps | 107 | — | ~2.4k | Automated safety check: Pass | MIT | |
| Store Listing Screenshotstherxmv/Telegram-Themer | 119 | — | ~2.5k | Automated safety check: Pass | None | |
| Maestro ImproveReinaMacCredy/maestro | 233 | — | ~1.9k | Automated safety check: Pass | MIT |
ShawnPana/phone-harness
Control the user's phone — an iPhone through the Mac's iPhone Mirroring window, an Android over adb, or a rented cloud Android: open apps, tap, type, swipe, read the screen.
MaaAssistantArknights/MaaAssistantArknights
分析 MaaAssistantArknights 上游仓库公开 Issue(https://github.com/MaaAssistantArknights/MaaAssistantArknights/issues/...
tloncorp/tlon-apps
Run a mobile QA checklist on a physical Android device over adb for tlon-apps, then triage what fails into fixes.
therxmv/Telegram-Themer
Generate TelegramThemer's Play Store listing images — capture the 8 required app screenshots on a running emulator/device by driving the real UI with adb, then composite them into the final…
ReinaMacCredy/maestro
Turn filed lessons into the smallest doctrine edit. An agent skill from ReinaMacCredy/maestro.
yang1ming/android-harness
Direct Android device control through ADB. An agent skill from yang1ming/android-harness.
saberzero1/quartz-syncer
Debug and investigate plugin issues in a running Obsidian instance — collect diagnostic data, inspect state, trace events, and identify root causes via the operability facade.
saberzero1/quartz-syncer
Post-change verification workflow — build, reload plugin in Obsidian, run health checks, and verify no regressions via the operability facade.
saberzero1/quartz-syncer
End-to-end publish verification — refresh status, publish files, verify the result, and confirm status changes via the operability facade.
Works with
Categories
UI verification workflow — open modals, query DOM contract selectors, interact with inputs, take screenshots, and validate UI rendering via the operability facade. Verify UI is an agent skill from saberzero1/quartz-syncer. UI verification workflow — open modals, query DOM contract selectors, interact with inputs, take screenshots, and validate UI rendering via the operability facade.
Verify UI fits situations like: tasks that involve Mobile testing and debugging.
Run `npx skills add saberzero1/quartz-syncer --skill verify-ui -a claude-code`. Or copy the skill folder (.agents/skills/verify-ui in saberzero1/quartz-syncer) into .claude/skills/verify-ui in your project. Claude Code loads it when a task matches its description.
Run `npx skills add saberzero1/quartz-syncer --skill verify-ui -a codex`. Or copy the skill folder (.agents/skills/verify-ui in saberzero1/quartz-syncer) into .agents/skills/verify-ui 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 saberzero1/quartz-syncer --skill verify-ui -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/verify-ui, .gemini/skills/verify-ui, .github/skills/verify-ui and .opencode/skills/verify-ui in your project.
Going by SKILL.md and its folder, Verify UI needs the command-line tools its instructions call (npm).
SKILL.md names 1 domain. In commands or code: github.com; the agent is likely to contact it 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.
Verify UI is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.3k tokens (SKILL.md is roughly 9.1k 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 Verify UI: Phone Harness (ShawnPana/phone-harness, 3.2k stars), Maa Issue Log Analysis (MaaAssistantArknights/MaaAssistantArknights, 24k stars), Mobile QA (tloncorp/tlon-apps, 107 stars) and Store Listing Screenshots (therxmv/Telegram-Themer, 119 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
saberzero1 (a GitHub user) maintains it in saberzero1/quartz-syncer, which has 140 GitHub stars. The repository holds 4 skills in this directory. The repository was last updated on September 30, 2026.
Source: saberzero1/quartz-syncer on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.