Install
openclaw skills install awesome-geelark-skillInteract with GeeLark Cloud Phone API for managing cloud phones, automation tasks, and social media operations. Use when asked to create cloud phones, manage phones, run automation tasks on TikTok/Instagram/Facebook/YouTube/Reddit, or interact with GeeLark services.
openclaw skills install awesome-geelark-skill⚠️ EXPERIMENTAL PROJECT: This skill is designed for AI agents. It contains safety mechanisms but should NOT be used directly in production without testing.
Configuration: assets/config.json (auto-loads token and base URL)
🔒 Security Notice
Required Dependencies (not auto-installed):
adb(Android Debug Bridge) — must be available in system PATHuiautomator2— Python package for device automationCredential Handling:
- API credentials (token, appId, apiKey) are stored in
assets/config.json- This file is protected by
.gitignore— never commit it- Set restrictive permissions:
chmod 600 assets/config.json- ⚠️RPA tasks require third-party account login. We recommend completing login in GeeLark first. Never send account credentials to the agent.
- Logs are written to
logs/cloudphone/— review and mask sensitive data before sharingAutonomous Execution:
- This skill runs local subprocess commands (
adb,glogin) and accesses API credentials- Do not enable unattended autonomous invocation until you've validated behavior in a sandbox
- Always use human confirmation for destructive operations (deletion, RPA with account credentials)
- ⚠️ RPA tasks require third-party account login. We recommend completing login in GeeLark first. Never send account credentials to the agent.
Ensure adb (Android Debug Bridge) is available in your system PATH:
# macOS
brew install android-platform-tools
# Ubuntu/Debian
sudo apt update && sudo apt install adb
# Windows
# Option 1: Using winget
winget install Google.AndroidSDK
# Option 2: Download Platform Tools from https://developer.android.com/studio/releases/platform-tools
# Extract and add to system PATH manually
Verify installation:
adb version
💡 Troubleshooting: If
adbis not found after installation, restart your terminal or add it to PATH manually.
Use a virtual environment to avoid conflicts with system packages:
# Create virtual environment
python3 -m venv .venv
# Activate (macOS/Linux)
source .venv/bin/activate
# Activate (Windows)
.venv\Scripts\activate
# Install dependencies
pip install requests uiautomator2
⚠️ Alternative (not recommended): If you must install system-wide:
pip install requests uiautomator2 --break-system-packages
Before starting cloud phone operations, run the doctor script to verify all dependencies:
# Basic check (environment, ADB, network, API)
python scripts/doctor.py
# Include phone-specific checks
python scripts/doctor.py --phone-id <phone_id>
# Include uiautomator2 connectivity test
python scripts/doctor.py --phone-id <phone_id> --serial 192.168.1.100:5555
# Output as JSON (for programmatic use)
python scripts/doctor.py --json
The doctor checks:
requests, uiautomator2)--phone-id provided)--serial provided)python3 scripts/init_config.py
This creates assets/config.json with your credentials (protected by .gitignore).
from scripts.geelark_boot_helper import list_cloud_phones
# Token auto-loads from config
phones = list_cloud_phones()
for phone in phones:
print(f"{phone['serialName']} - {phone['id']}")
from scripts.geelark_boot_helper import boot_and_connect
# Token auto-loads from config
adb_info = boot_and_connect("phone_id")
if adb_info:
print(f"ADB: {adb_info['ip']}:{adb_info['port']}, PWD: {adb_info['pwd']}")
Before operating cloud phones:
from scripts.geelark_client import GeeLarkClient
from scripts.geelark_boot_helper import list_cloud_phones
# Initialize client (auto-loads config)
client = GeeLarkClient(task_name="my_task", phone_id="batch")
# Check balance
wallet = client.wallet()
balance = wallet['data']['balance']
gift_money = wallet['data'].get('giftMoney', 0)
if balance <= 0 and gift_money <= 0:
print("❌ Insufficient balance! Please recharge.")
exit(1)
# List phones
phones = list_cloud_phones()
for phone in phones:
print(f" {phone['serialName']} (ID: {phone['id']})")
# Create single phone
response = client.call("/open/v1/phone/addNew", {
"mobileType": "Android 13",
"data": [{"profileName": "MyPhone"}]
})
# Create multiple phones (requires Pro plan)
response = client.call("/open/v1/phone/addNew", {
"mobileType": "Android 13",
"data": [
{"profileName": "Phone1"},
{"profileName": "Phone2"}
]
})
from scripts.geelark_boot_helper import boot_and_connect
# This function handles:
# - Balance check
# - Cloud phone status check
# - Start cloud phone (if stopped)
# - Enable ADB (if disabled)
# - Return ADB connection info
# Token auto-loads from config
adb_info = boot_and_connect("phone_id")
Critical: Must use appVersionId, NOT appName
# Search and install TikTok (auto-select best match)
python scripts/install_app.py --phone-id <phone_id> --name TikTok
# Exclude TikTok Lite
python scripts/install_app.py --phone-id <phone_id> --name TikTok --exclude Lite
# Install specific version directly
python scripts/install_app.py --phone-id <phone_id> --name Instagram --version-id <appVersionId>
# Step 1: Find app and get appVersionId
response = client.call("/open/v1/app/installable/list", {
"envId": "phone_id",
"name": "TikTok",
"page": 1,
"pageSize": 20
})
app_version_id = response['data']['items'][0]['appVersionInfoList'][0]['id']
# Step 2: Install using appVersionId
response = client.call("/open/v1/app/install", {
"envId": "phone_id",
"appVersionId": app_version_id
})
Recommended: Use PhoneManager for session tracking and auto-close.
from scripts.phone_manager import PhoneManager
# Method 1: Context manager (recommended)
with PhoneManager(timeout_minutes=5) as manager:
manager.start_monitor()
# Connect using phone_id (required)
d = manager.connect_device("phone_id_123", ip, port, pwd, name="Android15")
# Perform operations
d(text="Submit").click()
manager.record_activity("phone_id_123")
# Automatically stops all phones and saves logs on exit
# Method 2: Manual control
manager = PhoneManager(timeout_minutes=5)
manager.start_monitor()
# ... operations ...
manager.stop_all()
manager.client.save_log()
| Mechanism | Description |
|---|---|
| Balance Check | Auto-checks balance before starting cloud phones |
| Energy Saving | Auto enables energySavingMode=1 to reduce costs |
| Deletion Safeguards | Anti-automation mechanism: requires interactive terminal, explicit ID + 'YES' confirmation, and enforced delays to prevent scripted or accidental deletion |
| Auto-Close | PhoneManager auto-closes idle devices |
| Endpoint Whitelist | Only documented endpoints can be called |
| Logging | All operations logged to logs/cloudphone/ |
⚠️ Deletion Safety: AI agents must follow the Deletion Workflow. The
delete_helper.pyscript includes multiple anti-automation safeguards:
- Interactive terminal verification
- Input timing validation
- Mandatory delay before final confirmation
If the script blocks execution, instruct the user to run manually in their terminal.
adb must be installed and available in PATH (see First Time Setup)uiautomator2 Python package installed (see Python Environment)If uiautomator2 operations seem slow or hang, run the smoke test to identify the bottleneck:
# Basic connectivity and UI dump test
python scripts/ui_smoke_test.py 192.168.1.100:5555
# Test with app start
python scripts/ui_smoke_test.py 192.168.1.100:5555 --package com.zhiliaoapp.musically
# Custom timeout per step (default: 30s)
python scripts/ui_smoke_test.py 192.168.1.100:5555 --timeout 60
# Output as JSON
python scripts/ui_smoke_test.py 192.168.1.100:5555 --json
The smoke test checks each step with individual timeouts:
u2.connect(serial)d.info (current activity)d.dump_hierarchy()d.app_start(package) (if package provided)Since this skill is designed for AI agents that need to recognize the current screen state, the recommended workflow is:
Identify UI Structure: Use uiautomator2 to dump the current page hierarchy (dump_hierarchy()), enabling the agent to understand the screen layout.
text, resource-id, content-desc, or classbounds) for verification or fallback operationsdump_hierarchy() fails or returns empty, proceed to Step 3 immediatelyPrioritize uiautomator2 Operations: If elements can be identified and interacted with via the UI hierarchy, use uiautomator2 for clicks, inputs, and swipes.
d(text="Button").click() or d(resourceId="com.example:id/btn").click()d(text="Username").set_text("hello")d.swipe(x1, y1, x2, y2) or d.swipe_ext("up")d(text="Expected Text").wait(timeout=10) before interactionVerify & Retry: After each operation, execute dump_hierarchy() again to confirm the previous action succeeded.
Fallback to ADB Screenshots: If elements cannot be recognized or operated via uiautomator2, use ADB screenshots to visually confirm the state and perform coordinate-based operations.
d.screenshot("/tmp/screen.png") or via ADB screencapd.click(x, y) or subprocess.run(['adb', '-s', 'device', 'shell', 'input', 'tap', x, y])subprocess.run(['adb', '-s', 'device', 'shell', 'input', 'swipe', x1, y1, x2, y2])import uiautomator2 as u2
import subprocess
# Connect
d = u2.connect(f"{adb_info['ip']}:{adb_info['port']}")
# Authenticate (MUST DO IMMEDIATELY)
subprocess.run(['adb', '-s', f"{adb_info['ip']}:{adb_info['port']}",
'shell', 'glogin', adb_info['pwd']], capture_output=True)
# Get UI hierarchy (Step 1: Identify)
xml = d.dump_hierarchy()
# Find and click element (Step 2: Prioritize uiautomator2)
d(text="Submit").click()
# Input text
d(text="Username").set_text("hello world")
# Screenshot (Step 3: Fallback)
d.screenshot("/tmp/screen.png")
# Or using ADB
subprocess.run(['adb', '-s', f"{adb_info['ip']}:{adb_info['port']}",
'shell', 'screencap', '-p', '/sdcard/screen.png'])
subprocess.run(['adb', '-s', f"{adb_info['ip']}:{adb_info['port']}",
'pull', '/sdcard/screen.png', '/tmp/screen.png'])
See: references/cloudphone_operations.md for complete guide.
After app installation or first launch, Android shows permission/system dialogs. Use the reusable handler to auto-dismiss them:
from scripts.handle_android_permissions import handle_all_dialogs
# Handle all dialogs: permissions (allow/deny) + system dialogs
result = handle_all_dialogs(d, permission_action="allow")
print(f"Handled {result['total']} dialogs")
# Or handle only permission dialogs (deny all)
from scripts.handle_android_permissions import handle_permission_dialogs
handle_permission_dialogs(d, action="deny", max_retries=5)
# Or handle only system dialogs (Not Now, Close, Done, etc.)
from scripts.handle_android_permissions import handle_system_dialogs
handle_system_dialogs(d, max_retries=3)
As a standalone script:
# Allow all permissions
python scripts/handle_android_permissions.py 192.168.1.100:5555
# Deny all permissions
python scripts/handle_android_permissions.py 192.168.1.100:5555 --action deny
# Handle up to 10 dialogs
python scripts/handle_android_permissions.py 192.168.1.100:5555 --max-retries 10
The handler supports:
Allow, Allow, Don't Allow, Don't Allow (curly quotes)允许, 同意, 拒绝, 取消, 关闭Close, Done, Not Now, 稍后GeeLark provides built-in RPA tasks for 9 platforms:
See: references/api_reference.md for complete endpoint list and parameters
| Document | Description | When to Read |
|---|---|---|
references/api_reference.md | Complete API endpoint list | Need to look up endpoints/parameters |
references/error_codes.md | All error codes and solutions | API call fails |
references/best_practices.md | Safety and performance tips | Planning operations |
references/cloudphone_operations.md | ADB/uiautomator2 guide | Working with device UI |
references/auto_close.md | Auto-close mechanism | Managing idle devices |
| Code | Description | Action |
|---|---|---|
0 | Success | ✅ |
41001 | Balance not enough | Recharge account |
42001 | Cloud phone does not exist | Check phone ID |
42002 | Cloud phone is not running | Start phone first |
See: references/api_reference.md for complete list.
The following error codes are used by local diagnostic scripts (doctor.py, boot_and_connect(), etc.):
| Error Code | Severity | Description | Quick Fix |
|---|---|---|---|
ENV_DEPENDENCY_MISSING | 🔴 Critical | Python package or system tool not installed | Run doctor: python scripts/doctor.py |
NETWORK_DNS_FAILED | 🔴 Critical | Cannot reach GeeLark API | Check DNS, firewall, baseUrl in config |
GEELARK_API_FAILED | 🔴 Critical | API authentication or call failed | Verify token: python scripts/init_config.py |
PHONE_START_TIMEOUT | 🟡 Warning | Phone did not start within timeout | Check balance, retry after few minutes |
ADB_NOT_FOUND | 🔴 Critical | ADB not in PATH | Install: brew install android-platform-tools |
ADB_CONNECT_FAILED | 🔴 Critical | Cannot connect to ADB device | Start phone first with boot_and_connect() |
GLOGIN_REQUIRED | 🔴 Critical | ADB authentication needed | Run: adb -s <ip:port> shell glogin <pwd> |
UIAUTOMATOR_TIMEOUT | 🟡 Warning | uiautomator2 operation timed out | Run smoke test: python scripts/ui_smoke_test.py <serial> |
UIAUTOMATOR_CONNECT_FAILED | 🔴 Critical | Cannot connect to uiautomator2 | Check ADB connection first |
APP_INSTALL_CANDIDATE_AMBIGUOUS | 🟡 Warning | Multiple app matches found | Use --exclude flag or --version-id |
INSUFFICIENT_BALANCE | 🔴 Critical | Account balance too low | Recharge via GeeLark dashboard |
CONFIG_LOAD_FAILED | 🔴 Critical | Cannot load config file | Run: python scripts/init_config.py |
See: scripts/error_codes.py for complete list and recommendations.
Critical Directives:
wallet()) before initiating any cloud phone operations.phone_id (UUID) for all API calls, not serialName.video parameter is a string.video/images parameters are arrays.Image (capital I), not images.Email, not account.assets/config.json. Do not pass token manually.logs/cloudphone/ upon task completion.tok_abc...xyz) in outputs.⚠️ AI agents MUST follow this exact sequence for deletion operations. Never skip steps or auto-execute.
from scripts.geelark_boot_helper import list_cloud_phones
phones = list_cloud_phones()
Output a clear table like:
📱 Current Cloud Phones:
| ID (UUID) | Name | Status |
|----------------------------------------|-----------|----------|
| a1b2c3d4-e5f6-7890-abcd-ef1234567890 | Android13 | Running |
| b2c3d4e5-f6a7-8901-bcde-f12345678901 | Android15 | Stopped |
Prompt the user with:
⚠️ Deletion is permanent and cannot be undone.
Please confirm which phone IDs to delete by replying with the IDs and typing 'YES'.
Example: "Delete a1b2c3d4... YES"
You MUST pause execution and wait for the user's explicit response.
Once the user confirms, run:
python3 scripts/delete_helper.py
Or call the deletion API with explicit DELETE_CONFIRMED code.
🔒 Security Rule: AI agents are FORBIDDEN from bypassing confirmation. If you cannot wait for user input, do not attempt deletion. Instruct the user to run
python3 scripts/delete_helper.pymanually.
assets/config.json:
chmod 600 assets/config.json
logs/cloudphone/ for sensitive data and redact as neededadb and uiautomator2 are from official sourcesassets/config.json fileSkill Repository: https://github.com/GeeLark/awesome-geeLark-skill
API Documentation: https://github.com/GeeLark/geelark-openapi