phonebase-cloud/phonebase-skills/phonebase-skill-creator
Claude Code and agent skill by phonebase-cloud/phonebase-skills
- community
Checking that the SKILL.md file is still in the repository.
Write PhoneBase app skills — the scripted automation packages that turn Android apps into pb CLI subcommands. Use this skill whenever the user asks to create a new skill, add commands to an existing skill, write automation scripts for an app, scaffold a skill, or debug/fix a skill script. Trigger phrases include "create a skill for X", "write a pb skill", "add a command to the skill", "scaffold a new skill", "automate X app", "write a script for pb", even if the user doesn't mention "skill" explicitly. This skill covers the full authoring workflow — research, scaffolding, scripting, testing, and iteration.
Install
npx vskill@latest install phonebase-cloud/phonebase-skills/phonebase-skill-creatorSKILL.md
PhoneBase Skill Creator
Write app skills — scripted automation packages that turn an Android app into pb CLI subcommands. After installing a skill, the user gets commands like pb googleplay search "telegram" or pb gmail compose.
Workflow
Creating a skill is an iterative process:
- Research the app — figure out its package name, deeplink schemes, key screens, and UI patterns
- Scaffold —
pb skills new <name> --package <pkg>to create the directory and extract the app icon - Write scripts — start with
open.js,close.js,state.js, then add business commands - Test on a real device — run each command, check the output shape, try edge cases
- Iterate — fix issues, handle dialog interruptions, improve stability
Don't try to get it perfect in one pass. Write the simplest version first, test it, then improve based on what actually happens on the device. Real Android devices are messy — apps update, dialogs pop up, UI elements move.
Directory Layout
Rules:
- Files starting with
_or.inscripts/are not registered as commands - One file = one command. Filename becomes the command name (
search.js→pb <skill> search) - Skill name: lowercase
[a-z0-9_-], 1–64 chars, start with letter or digit
SKILL.md Frontmatter
| Field | Required | Description | |
|---|---|---|---|
name | Yes | Must match directory name | |
display_name | No | Human-readable app name | |
description | No | One-line description | |
package | No | Android package name | |
category | No | Category slug | |
requires | No | Dependencies (auto-installed) |
Below the frontmatter is free-form markdown documentation (not parsed by the scanner).
JSDoc Command Protocol
The first `/ ... */` block** in each script declares the command:
@arg syntax
@arg <name>:<type>[modifier] [description]
| Type | Values | |
|---|---|---|
| Types | string int float bool path | |
! | Required | |
=<value> | Optional with default | |
* | Multi-value (--tags a --tags b) |
Reading args in script
SDK API
All methods return Promise. The SDK communicates with the pb daemon via Unix socket — PHONEBASE_DEVICE_ID is auto-injected.
Device Control
| Method | Purpose | |
|---|---|---|
pb.tap(x, y) | Tap at coordinates | |
pb.swipe(x1, y1, x2, y2) | Swipe (Bézier trajectory) | |
pb.input(text) | Type into focused field (appends, does not replace) | |
pb.keyevent(key) | Send key by string name: HOME BACK ENTER DEL MENU etc. |
App Management
| Method | Purpose | |
|---|---|---|
pb.launch(pkg) | Launch app's default Activity | |
pb.startActivity(opts) | Send custom Intent (action, data, package_name, component, extras) | |
pb.forceStop(pkg) | Kill app | |
pb.topActivity() | Get foreground Activity → {package_name, class_name} | |
pb.packagesList() | List installed packages | |
pb.installPackage(opts) | Install APK: {uri: "https://..." } or {uri: "/sdcard/..."} | |
pb.uninstallPackage(pkg) | Uninstall app |
UI Observation
| Method | Purpose | |
|---|---|---|
pb.dumpc() | Compact UI tree (text, bounds, clickable) — preferred | |
pb.dump() | Full XML hierarchy (when you need parent-child) | |
pb.screencap(opts?) | Screenshot image | |
pb.findTextInDump(dumpStr, text) | Find node → {bounds, center, line} or null | |
pb.waitText(text, opts?) | Poll dumpc until text appears (default 10s, 0.5s interval) | |
pb.tapText(text) | Find + tap in one call |
Other
| Method | Purpose | |
|---|---|---|
pb.browse(url, pkg?) | Open URL in browser | |
pb.clipboardGet() / pb.clipboardSet(text) | Clipboard | |
pb.displayInfo() | Screen resolution, density, rotation | |
pb.shell(cmd) | Raw shell → {stdout, stderr, code} | |
pb.pushFile(local, remote?) / pb.pullFile(path) | File transfer | |
pb.listFiles(path) | List directory | |
pb.run(path, args?) | Generic capability passthrough |
Output Format
Your script's stdout is only the business data JSON. pb automatically wraps it:
Three rules:
- Never add `status` field — metadata belongs in pb's
codefield - Use boolean / objects — not string status codes (
{logged_in: false}not{status: "needs_login"}) - Failure = `process.exit(1)` + stderr — pb converts non-zero exit to error response
Helper functions (put in _lib.js):
Standard Commands
Every app skill should provide at least open and close. state is strongly recommended.
| Command | Responsibility | Returns | Does NOT return | |
|---|---|---|---|---|
open | Launch only, return fast | top_activity, foreground | dump data, logged_in | |
state | Full introspection | top_activity, foreground, logged_in, account, visible_texts | — | |
close | Force-stop only | top_activity | extra data |
The reason for this separation: callers choose what they need. open is fast because it skips the dump. state is thorough because that's its job. Mixing them makes both slower and harder to reason about.
open.js
state.js
_lib.js Essentials
Every skill needs dump parsing utilities:
Stability Patterns
1. Deeplinks over UI taps
Deeplinks are faster, more stable, and survive app version updates. Always check if the app supports them before writing tap sequences:
Why this matters: a deeplink is one API call. The UI tap equivalent is "tap search icon → wait for keyboard → type text → tap search button" — four steps, each of which can fail if the UI layout changes.
2. Clear input before typing
pb.input() appends text. If the user runs the same search command twice, the second keyword gets appended to the first:
3. Handle dialog interruptions
Apps often interrupt with Google Sign-In, permission dialogs, or update prompts. Your script needs to handle these or it will get stuck:
4. NAF (Not Accessibility Friendly) buttons
Icon-only buttons without text or content-desc can't be found by text. Use geometry instead — "the clickable element in the top-right corner":
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 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 repositoryCheckingskills/phonebase-skill-creator/SKILL.md
Popularity
- Repository stars
- 53
- Repository forks
- 5
- 7-day trend score
- 20
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 27 Apr 2026, 6 months ago.
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/phonebase-cloud/phonebase-skills/phonebase-skill-creator)