Skip to content

💻 CLI Reference

The ghost CLI is the primary entry point for Ghost in the Droid. It’s task-first: a bare positional is an agent task; a reserved first token is a subcommand.

Terminal window
ghost "check reddit for AI news" --device asus # run a task (marquee use)
ghost devices # list connected phones
ghost setup # first-run wizard
ghost mcp install --client claude-code # wire into your agent client
ghost up # boot server + dashboard

Installed by pip install ghost-in-the-droid. Three binaries ship:

BinaryStatusNotes
ghostprimaryTask-first CLI (since v1.3.0)
gitd⚠️ deprecatedPrints warning, still works, delegates to ghost legacy path
android-agent⚠️ deprecatedSame as gitd
  • A bare positional is treated as an agent task, run against a device — ghost "check reddit" --device asus
  • A reserved first token is a subcommand — ghost devices, ghost skill list
  • Reserved verbs win. To run a task whose first word is a reserved verb, quote it: ghost "record my day"
  • -- forces prompt mode explicitly: ghost -- up my code coverage

Reserved subcommands: devices, setup / configure, config, mcp, up, doctor, login, skill, help

Everywhere config is read, precedence is:

explicit flag > GHOST_* env var > ~/.ghost/config.toml > built-in / detected default

This applies to backend, model, mode, and device selection consistently.


Terminal window
ghost "<task>" [--device D] [--mode fast|vision|reason] [--backend B] [--model M]

The bare-positional invocation. Runs a live agent turn: takes your task text, picks a device + LLM backend + mode, and drives the phone via the 62-tool MCP surface.

Flags:

FlagAliasesDefaultDescription
--device-d, --udidauto-pick sole deviceDevice alias (from ~/.ghost/devices.toml) or raw ADB serial / ios:<udid>
--modefastfast (text-only), vision (screenshot-driven), reason (deeper multi-step)
--backendresolvedProvider slug: claude-code, anthropic, openrouter, ollama, vllm, on-device
--modelbackend defaultSpecific model id (e.g. claude-sonnet-4.5, gpt-oss-20b, gemma-3-1b-it)

Examples:

Terminal window
# Simplest — auto-picks the sole connected phone + configured backend + fast mode
ghost "open Instagram and DM alex hey"
# Explicit device alias + reasoning mode
ghost "book me the earliest gym slot tomorrow" --device asus --mode reason
# Force a specific backend + model
ghost "summarize my inbox" --backend openrouter --model anthropic/claude-sonnet-4.5
# iOS
ghost "post my Duolingo streak screenshot to X" --device ios:00008110-...

First-run behavior: if ~/.ghost/config.toml doesn’t exist AND no GHOST_BACKEND env is set AND no --backend flag is passed AND stdin is a TTY, ghost drops into the setup wizard before running your task, then resumes.

Device selection failure modes:

  • No --device and no configured default and exactly one device connected → auto-picks with a warning
  • Zero devices → error, suggests ghost setup
  • Two or more devices → error listing candidates, requires explicit --device

Terminal window
ghost devices

List connected Android + iOS devices with model name, configured alias, and platform.

Example output:

asus-rog-8f7d2a1c ASUS ROG Phone 7 (asus) [android]
galaxy-a15-9c8f Samsung Galaxy A15 (a15) [android]
ios:00008110-... iPhone 15 Pro (main) [ios]
Aliases in ~/.ghost/devices.toml: asus→asus-rog-8f7d2a1c, a15→galaxy-a15-9c8f, main→ios:00008110-...

iOS discovery requires IOS_APPIUM_URL / IOS_DEVICE_UDID to be set — see iOS Setup. Android discovery via adb devices.


First-run wizard, or non-interactive scripted config.

Terminal window
ghost setup

Detects available LLM backends (checks for claude CLI, ANTHROPIC_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY, local Ollama, local vLLM, on-device app), lists them ranked, asks for:

  1. Backend choice
  2. Model (defaults to backend default; for Ollama, picks a local model)
  3. Device nickname (auto-suggests phone if one device connected)
  4. Default mode (fast / vision / reason)

Writes ~/.ghost/config.toml + ~/.ghost/devices.toml. Confirms with the written path.

Terminal window
ghost setup --backend BACKEND [--model MODEL] [--mode MODE] [--device ALIAS:SERIAL]
FlagDefaultDescription
--backendrequiredProvider slug (see Precedence chain for valid values)
--modelbackend defaultSpecific model id, blank = backend default
--modefastfast / vision / reason
--devicenoneALIAS:SERIAL to register an alias, or bare SERIAL (alias == serial)

Example:

Terminal window
ghost setup --backend anthropic --model claude-sonnet-4.5 --mode reason --device asus:asus-rog-8f7d2a1c

Fails with exit 2 if not a TTY and --backend is not provided.


Read + write the flat, whitelisted keys in ~/.ghost/config.toml.

Terminal window
ghost config path # print config path
ghost config get <dotted.key> # print current value
ghost config set <dotted.key>=<val> # set + save

Known keys:

KeyTypeNotes
backend.namestringProvider slug (claude-code, anthropic, openrouter, ollama, vllm, on-device)
backend.modelstringModel id (backend-specific)
defaults.modestringfast / vision / reason (validated)
defaults.devicestringAlias from devices.toml, or raw serial
dashboard.portintPort for ghost up dashboard (default from settings)

Examples:

Terminal window
ghost config path # → /home/user/.ghost/config.toml
ghost config get backend.name # → anthropic
ghost config set defaults.mode=reason # → defaults.mode = reason
ghost config set dashboard.port=5057

Unknown keys exit 2 with a list of valid keys. Invalid values (e.g. mode=warp) exit 2 with a helpful error.


Register Ghost’s MCP server with your agent client. All clients get the same stdio server (android-agent-mcp binary, server name android-agent), so the 62-tool surface is identical everywhere.

Terminal window
ghost mcp install --client <name>
--clientConfig file writtenMerge behavior
claude-codeclaude mcp add (falls back to project-local .mcp.json)CLI adds; file falls back if claude not on PATH
cursor~/.cursor/mcp.jsonMerged into mcpServers map
codex~/.codex/config.tomlAppended [mcp_servers.android-agent] block; no-op if already present
opencode~/.config/opencode/opencode.jsonMerged into mcp map with type: local, enabled: true
agy~/.gemini/config/mcp_config.jsonMerged into mcpServers map (Antigravity CLI)
antigravity(alias for agy)Same as agy — early docs used this spelling

Merge-not-clobber: all JSON writes read + merge existing config (never overwrite), so your other MCP servers stay intact. Malformed existing JSON is a hard error (fix or remove the file first).

Example:

Terminal window
ghost mcp install --client claude-code # → Registered 'android-agent' with Claude Code (claude mcp add).
ghost mcp install --client cursor # → Registered 'android-agent' in ~/.cursor/mcp.json (Cursor).

Boot the FastAPI server + Vue dashboard.

Terminal window
ghost up [--host HOST] [--port PORT]
FlagDefaultDescription
--host127.0.0.1Bind host. Use 0.0.0.0 to expose on LAN.
--portfrom dashboard.port in config, else settings default (5055)Bind port

Loads .env from the current working directory if present (uvx/pipx runs work from anywhere). Serves:

  • Dashboard at http://<host>:<port>/
  • REST API under /api/* — see REST Endpoints
  • Swagger UI at /docs
  • Scheduler daemon in a background thread

Ctrl+C stops the server cleanly.


Environment preflight — green / yellow / red checklist.

Terminal window
ghost doctor

Checks:

  • Python version + Ghost install
  • adb on PATH + version
  • Connected devices (Android + iOS)
  • Configured backend + credentials / usability
  • Port availability for ghost up
  • Required Python deps
  • Optional: MLX / MediaPipe / llama.cpp availability for on-device paths

Exit codes:

  • 0 — all checks passed (warnings OK)
  • 1 — at least one fail; prints hints per failed check

Sign into Ghost’s claude-code backend via your Claude Max / Pro subscription — no API key needed.

Terminal window
ghost login [--relogin]

Delegates to claude auth login (Anthropic’s own OAuth flow). Ghost never handles or stores the token; the claude CLI owns it (refresh included). If claude isn’t installed, prints install instructions and exits 1.

FlagDescription
--reloginForce re-authentication even if already signed in

Manage the skill library. Skills live in the packaged gitd/skills/ dir plus user-installed skills in ~/.ghost/skills/.

Terminal window
ghost skill install <target> [--force]
ghost skill list
ghost skill update <name>
ghost skill remove <name> [--force]
ghost skill validate <path>
ghost skill search <query>

Install a skill from the registry, a GitHub URL, or a local path.

Arg / flagDescription
targetRegistry name (e.g. tiktok), GitHub URL, or local path to a skill dir
--force, -fInstall even if validation fails

Examples:

Terminal window
ghost skill install tiktok # registry
ghost skill install https://github.com/user/my-skill # GitHub
ghost skill install ./my-skill # local path
ghost skill install ./flaky-skill --force # bypass validation

List installed skills (packaged + user-installed).

Re-fetch the latest version of an installed skill. Reads repo_url from the skill’s skill.yaml and re-clones/copies. Errors if the skill isn’t installed or has no repo_url.

Remove a user-installed skill. --force allows removing built-in packaged skills too.

Validate a skill directory against the schema without installing. Useful for skill authors.

Search the registry by name + description.

For skill execution (running an installed skill against a device), see the Advanced section below or the Skill System docs.


Ghost respects these environment variables. Precedence: flag > env > config.toml > default.

VariableOverridesNotes
GHOST_BACKEND--backend / backend.nameProvider slug
GHOST_MODEL--model / backend.modelModel id
GHOST_MODE--mode / defaults.modefast / vision / reason
GHOST_CONFIG_DIR~/.ghost/ locationTesting / non-default homes
GHOST_HOME_OVERRIDE$HOME for MCP installTesting

Only needed if you use the corresponding backend:

VariableUsed byNotes
ANTHROPIC_API_KEY--backend anthropicDirect Anthropic API
OPENROUTER_API_KEY--backend openrouterOpenRouter (multi-model gateway)
OPENAI_API_KEY(OpenAI-compatible flows)See installation docs
OLLAMA_BASE_URL--backend ollamaDefault http://localhost:11434
GITD_VLLM_BASE_URL--backend vllmYour vLLM / llama.cpp OpenAI-compatible endpoint

No key needed for: claude-code (uses your Claude Max/Pro subscription via ghost login), on-device (runs on the phone itself — see On-Device LLM).

Full environment variable reference (feature gates, iOS setup, observability): Installation → Optional AI Features.


All under ~/.ghost/ (overridable with GHOST_CONFIG_DIR):

FilePurpose
~/.ghost/config.tomlDefault backend, model, mode, device, dashboard port
~/.ghost/devices.tomlalias = "serial" map (also editable via ghost setup + set_device_alias)
~/.ghost/skills/User-installed skills (installed via ghost skill install)
~/.ghost/logs/CLI logs

config.toml schema (all sections + keys optional):

[backend]
name = "anthropic"
model = "claude-sonnet-4.5"
[defaults]
mode = "reason"
device = "asus"
[dashboard]
port = 5055

devices.toml:

[devices]
asus = "asus-rog-8f7d2a1c"
a15 = "galaxy-a15-9c8f"
main = "ios:00008110-0012345678901234"

gitd and android-agent are the pre-v1.3.0 CLI names. They still work — they map to the same underlying entry point — but print a deprecation warning:

⚠ 'gitd' is deprecated — use 'ghost' instead

Migration is straightforward: replace gitd <cmd> with ghost <cmd> (all subcommands are compatible: up, doctor, login, skill). Scripts using gitd should be updated but won’t break.


For programmatic / advanced use, Ghost exposes several Python module entrypoints beyond the ghost CLI:

Terminal window
python -m gitd.skills._run_skill \
--skill tiktok \
--workflow upload_video \
--device YOUR_DEVICE_SERIAL \
--params '{"video_path": "/tmp/video.mp4"}'

This is what the scheduler calls internally for skill_workflow and skill_action jobs. See Skill System.

Terminal window
python -m gitd.skills.auto_creator \
--package com.zhiliaoapp.musically \
--device YOUR_DEVICE_SERIAL \
--max-depth 3 --max-states 20 --settle 1.5
FlagDefaultDescription
--packagerequiredAndroid package name
--devicerequiredADB serial
--max-depth3BFS depth
--max-states20Max unique states
--settle1.5Seconds after each tap
--outputautoOutput directory

Used to bootstrap a skill from an unknown app. See Skill Creator.

Terminal window
android-agent-mcp # or: python -m gitd.mcp_server

Runs the MCP server on stdio. ghost mcp install --client <name> wires this up for you — you rarely invoke it directly.

Terminal window
python -m pytest tests/ -v
DEVICE=<serial> python -m pytest tests/test_04_crawl.py -v

Test suite requires a connected device for integration tests; unit tests run without one.