App Store Optimization CLI
Research ASO keywords, inspect competition, and manage results from one local-first CLI.
What Is It?
- Fast, free keyword research and visibility tracking
- Keyword scoring with popularity + difficulty + brand classification in one command
- Local ASO dashboard for reviewing keyword/app data
- MCP tool (
aso_evaluate_keywords) for agent workflows and automated keyword research
ASO Dashboard
MCP
The dashboard keywords shown above were discovered and added automatically by an agent using the MCP tool.
Install
npm install -g aso-cli
Note: requires Node.js >=18.14.1.
Apple Search Ads Setup
ASO commands require Apple Search Ads setup.
Prerequisites
- App Store Connect account
- App ID of a published app you can access
- No campaign creation required
- No billing information required
Setup
- Create/sign in: https://searchads.apple.com
United States.
- Open Apple Search Ads Advanced: https://searchads.apple.com/advanced
- Click your account name in the top-left corner.
- Under Campaign Groups, click Settings.
- Click Link Accounts.
- Select your App Store Connect account and save.
- Copy an App ID from your App Store URL (number after
id)
https://apps.apple.com/us/app/example-app/id123456789
App ID is 123456789 in this example.
- Run
aso authand complete Apple ID + password + 2FA in terminal
- You may see a missing billing information warning; this can be safely ignored.
- Ensure all campaign groups are linked to a valid App Store Connect account.
- Troubleshoot App Store Connect account linking
Quick Start
# Authenticate once
aso auth
Fetch keyword metrics
aso keywords "meditation,sleep sounds,white noise"
Open dashboard
aso
Command Reference
| Command | What it does |
| ------------------------------- | ------------------------------------------------------- |
| aso | Starts the local dashboard (default command) |
| aso keywords "k1,k2,k3" | Fetches keyword popularity/difficulty and prints JSON |
| aso keywords "k1,k2" --stdout | Machine-readable mode for automation/agents |
| aso auth | Reauthenticates Apple Search Ads session |
| aso reset-credentials | Clears saved credentials/cookies |
| aso --primary-app-id | Sets primary App ID used for popularity requests |
Supported flags
--country: currentlyUSonly--primary-app-id: saved locally for future runs--min-popularity: filters out low-popularity keywords before enrichment--max-difficulty: filters out high-difficulty keywords after enrichment--app-id: associates keywords to this local app id (default:research)--exclude-existing: skips keywords already associated with the target app/country before evaluation--no-associate: skips app-keyword association writes for the currentaso keywordsrun
aso keywords:
- Association writes happen only after a successful command return.
- Without filters, requested keywords are associated.
- With
--min-popularityand/or--max-difficulty, only accepteditemsare associated. - With
--exclude-existing, already associated keywords are returned infilteredOutwithreason="already_associated"and are not re-associated. - With
--no-associate, no association write occurs.
Output Example (aso keywords "meditation")
{
"items": [
{
"keyword": "meditation",
"popularity": 45,
"difficultyScore": 62,
"minDifficultyScore": 38,
"isBrandKeyword": false
}
],
"failedKeywords": [],
"filteredOut": []
}
--stdout Contract
aso keywords " is the machine-readable contract.
- Success: exit code
0,stdoutcontains exactly one JSON object with:
items
- failedKeywords
- filteredOut
- Failure: exit code
!= 0,stdoutcontains exactly one JSON object with:
error.code (CLI_VALIDATION_ERROR or CLI_RUNTIME_ERROR)
- error.message
- optional error.help
- In
--stdoutmode, CLI logs and prompts are kept offstdoutso parsers can read one JSON payload safely.
{
"error": {
"code": "CLI_RUNTIME_ERROR",
"message": "Primary App ID is missing. Run 'aso --primary-app-id <id>' or run 'aso' in a terminal to set it, then retry this command with --stdout."
}
}
MCP
This package also installs aso-mcp with tool: aso_evaluate_keywords.
aso_evaluate_keywords runs aso keywords ... --stdout with default filters:
minPopularity = 6when omitted; accepts explicit values from0to100maxDifficulty = 70excludeExisting = false; settrueto return only keywords not already associated with the target app/country
keyword, popularity, difficulty, minDifficultyScore, isBrandKeyword).
Example MCP config:
{
"mcpServers": {
"aso": {
"command": "aso-mcp"
}
}
}
Current Scope
- Storefront support:
US - Multi-storefront support is planned
Project Docs
- Contribution guide: CONTRIBUTING.md
- Website architecture: docs/website-architecture.md