⚠️ 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:
bash
# 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:
bash
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:
bash
# 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:
bash
pip install requests uiautomator2 --break-system-packages
Before starting cloud phone operations, run the doctor script to verify all dependencies:
bash
# 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)bash
python3 scripts/init_config.py
This creates assets/config.json with your credentials (protected by .gitignore).
python
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']}")
python
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:
python
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']})")
python
# 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"}
]
})
python
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
bash
# 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>
python
# 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.
python
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()
MechanismDescriptionBalance CheckAuto-checks balance before starting cloud phonesEnergy SavingAuto enables energySavingMode=1 to reduce costsDeletion SafeguardsAnti-automation mechanism: requires interactive terminal, explicit ID + 'YES' confirmation, and enforced delays to prevent scripted or accidental deletionAuto-ClosePhoneManager auto-closes idle devicesEndpoint WhitelistOnly documented endpoints can be calledLoggingAll 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:
bash
# 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:
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 immediatelyuiautomator2 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 interactiondump_hierarchy() again to confirm the previous action succeeded.
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])python
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:
python
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:
bash
# 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
DocumentDescriptionWhen to Readreferences/api_reference.mdComplete API endpoint listNeed to look up endpoints/parametersreferences/error_codes.mdAll error codes and solutionsAPI call failsreferences/best_practices.mdSafety and performance tipsPlanning operationsreferences/cloudphone_operations.mdADB/uiautomator2 guideWorking with device UIreferences/auto_close.mdAuto-close mechanismManaging idle devices
CodeDescriptionAction0Success✅41001Balance not enoughRecharge account42001Cloud phone does not existCheck phone ID42002Cloud phone is not runningStart 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 CodeSeverityDescriptionQuick FixENV_DEPENDENCY_MISSING🔴 CriticalPython package or system tool not installedRun doctor: python scripts/doctor.py``NETWORK_DNS_FAILED🔴 CriticalCannot reach GeeLark APICheck DNS, firewall, baseUrl in configGEELARK_API_FAILED🔴 CriticalAPI authentication or call failedVerify token: python scripts/init_config.py``PHONE_START_TIMEOUT🟡 WarningPhone did not start within timeoutCheck balance, retry after few minutesADB_NOT_FOUND🔴 CriticalADB not in PATHInstall: brew install android-platform-tools``ADB_CONNECT_FAILED🔴 CriticalCannot connect to ADB deviceStart phone first with boot_and_connect()``GLOGIN_REQUIRED🔴 CriticalADB authentication neededRun: adb -s <ip:port> shell glogin <pwd>``UIAUTOMATOR_TIMEOUT🟡 Warninguiautomator2 operation timed outRun smoke test: python scripts/ui_smoke_test.py <serial>``UIAUTOMATOR_CONNECT_FAILED🔴 CriticalCannot connect to uiautomator2Check ADB connection firstAPP_INSTALL_CANDIDATE_AMBIGUOUS🟡 WarningMultiple app matches foundUse --exclude flag or --version-id``INSUFFICIENT_BALANCE🔴 CriticalAccount balance too lowRecharge via GeeLark dashboardCONFIG_LOAD_FAILED🔴 CriticalCannot load config fileRun: python scripts/init_config.py
See: scripts/error_codes.py for complete list and recommendations.
Critical Directives:
Pre-flight Check: Always verify account balance ( wallet()) before initiating any cloud phone operations.
Identifiers: Use phone_id (UUID) for all API calls, not serialName.
RPA Parameter Quirks:
video parameter is a string.video/ images parameters are arrays.Image (capital I), not images.Email, not account.Lifecycle Management: You must stop a running phone before deleting it (otherwise error 43009).
Auto-Configuration: Credentials load automatically from assets/config.json. Do not pass token manually.
Logging: Always save operation logs to logs/cloudphone/ upon task completion.
Credential Safety: Never print or log full API tokens, passwords, or proxy credentials. Use masked versions (e.g., tok_abc...xyz) in outputs.
Autonomous Restriction: Do not invoke RPA tasks with third-party account credentials without explicit human confirmation. Always require approval before executing social media automation that involves login credentials.
⚠️ RPA tasks require third-party account login. You should strongly recommend users complete login in GeeLark first. Never request account credentials from users under any circumstances.
⚠️ AI agents MUST follow this exact sequence for deletion operations. Never skip steps or auto-execute.
python
from scripts.geelark_boot_helper import list_cloud_phones
phones = list_cloud_phones()
Output a clear table like:
text
📱 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:
text
⚠️ 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:
bash
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.
Sandbox First: Test this skill in an isolated environment (VM/container) before production use
Credential Rotation: Implement regular credential rotation on a scheduled basis.
File Permissions: Restrict access to assets/config.json:
bash
chmod 600 assets/config.json
Log Review: Before sharing logs, review logs/cloudphone/ for sensitive data and redact as needed
Dependency Verification: Verify adb and uiautomator2 are from official sources
Never store or transmit credentials outside the assets/config.json file
Always confirm with the user before executing operations that involve:
Never bypass the double-confirmation mechanism for destructive operations
⚠️ RPA tasks require third-party account login. You should strongly recommend users complete login in GeeLark first. Never request account credentials from users under any circumstances.
Deletion Operations: Always follow the 5-step Deletion Workflow. List IDs → Ask for confirmation → STOP AND WAIT → Execute only after explicit user reply. Never auto-fill or chain deletion commands.
Skill Repository: https://github.com/GeeLark/awesome-geeLark-skill
API Documentation: https://github.com/GeeLark/geelark-openapi