@appeeky/spec 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +158 -5
  2. package/agents/appeeky-ads.md +50 -0
  3. package/agents/appeeky-aso.md +58 -0
  4. package/agents/appeeky-releases.md +47 -0
  5. package/agents/appeeky-reviews.md +53 -0
  6. package/agents/appeeky-social.md +54 -0
  7. package/agents/appeeky-ugc.md +56 -0
  8. package/agents/cofounder.md +36 -0
  9. package/dist/ads.d.ts +5 -2
  10. package/dist/ads.js +8 -4
  11. package/dist/agents.d.ts +47 -0
  12. package/dist/agents.js +88 -0
  13. package/dist/cli.js +582 -9
  14. package/dist/dataforseo.d.ts +139 -0
  15. package/dist/dataforseo.js +354 -0
  16. package/dist/experiments.d.ts +4 -4
  17. package/dist/metrics.d.ts +20 -0
  18. package/dist/metrics.js +4 -0
  19. package/dist/report.d.ts +5 -0
  20. package/dist/report.js +42 -0
  21. package/dist/reviews.d.ts +2 -2
  22. package/dist/schema.d.ts +95 -2
  23. package/dist/schema.js +35 -0
  24. package/dist/search-ads.d.ts +137 -0
  25. package/dist/search-ads.js +354 -0
  26. package/dist/seo.d.ts +87 -0
  27. package/dist/seo.js +391 -0
  28. package/dist/setup.js +39 -6
  29. package/dist/social.d.ts +129 -0
  30. package/dist/social.js +189 -0
  31. package/dist/transport.d.ts +1 -0
  32. package/dist/transport.js +1 -1
  33. package/dist/ugc-core.js +1 -0
  34. package/dist/ugc-local.d.ts +116 -0
  35. package/dist/ugc-local.js +174 -0
  36. package/dist/ugc.d.ts +149 -0
  37. package/dist/ugc.js +111 -0
  38. package/dist/visibility-core.js +96 -0
  39. package/dist/visibility-local.d.ts +159 -0
  40. package/dist/visibility-local.js +246 -0
  41. package/dist/visibility.d.ts +3 -0
  42. package/dist/visibility.js +1 -1
  43. package/package.json +7 -3
  44. package/skills/appeeky-spec/SKILL.md +14 -18
  45. package/skills/appeeky-spec-experiments/SKILL.md +12 -2
  46. package/skills/appeeky-spec-visibility/SKILL.md +33 -6
package/README.md CHANGED
@@ -44,7 +44,7 @@ npx @appeeky/spec verify # day 7 and day 14: did it work?
44
44
  | **What users and rivals say** | Reviews with a summary and drafted replies, competitors' listings and moves, and the category chart rank, one row a day. |
45
45
  | **AI visibility** | Whether ChatGPT, Claude, Gemini and Perplexity name your app, who they name instead and the pages they cite. |
46
46
  | **Ads and data** | Apple Search Ads, Meta and TikTok spend and installs, App Store Connect, Google Play and RevenueCat numbers as CSV your agent can read. |
47
- | **A weekly proposal** | Once a week an agent opens a pull request with one listing change, for a store with no release still being measured. It can run on your Claude plan. |
47
+ | **Specialists and a co-founder** | Six read-only specialist subagents (ASO, reviews, ads, releases, UGC, social) and a co-founder review that starts them, writes a brief to `appeeky/briefs/` and opens a pull request with one listing change. Run it as `/appeeky-cofounder`, or once a week on your Claude plan. |
48
48
 
49
49
  ## How a change goes live
50
50
 
@@ -66,7 +66,7 @@ Nothing reaches the stores until a person merges. The merge is the approval.
66
66
  | --- | --- |
67
67
  | **GitHub Actions** | `init --ci` writes three workflows: a check on every pull request, a push on merge, and a daily run that measures and commits. See [In pull requests](#in-pull-requests). |
68
68
  | **Your own server** | `docker compose up -d` on any VM: Hetzner, DigitalOcean, AWS, Google Cloud, Railway, Fly.io, Render or a machine in your office. See [Running without GitHub Actions](#running-without-github-actions). |
69
- | **Your computer** | Every command runs locally with `npx`. `examples/weekly/` has a cron script for the weekly proposal. |
69
+ | **Your computer** | Every command runs locally with `npx`. `examples/weekly/` has a cron script for the weekly co-founder review. |
70
70
  | **Other CI** | GitLab, Bitbucket or CircleCI: the same three triggers and commands. |
71
71
 
72
72
  Powered by [Appeeky](https://appeeky.com). Works with your own store keys on your machine, or with your Appeeky connection when you'd rather not handle keys.
@@ -83,6 +83,8 @@ appeeky/
83
83
  reviews/ # customer reviews (JSONL per month), summary.md, replies/ drafted for review
84
84
  competitors/ # one file per competitor: listing, ranks, recent reviews
85
85
  visibility/<country>.yaml # what ChatGPT, Claude, Gemini and Perplexity answer: named or not, who instead, cited pages
86
+ seo/ # Google Search Console for the website: clicks per day, queries, pages, summary.md
87
+ search-ads/ # Apple Search Ads on your own key: spend and installs per day, keywords, search terms
86
88
  category.csv # rank in the category chart, one row a day
87
89
  playbook.md # what worked and what did not for this app
88
90
  .appeeky/data/ # analytics, ads and revenue as CSV (gitignored; data.commit moves it to appeeky/data/)
@@ -126,7 +128,9 @@ A field you leave out of a listing file is not managed by the spec: it is never
126
128
  | `ads` | Spend, installs and cost per install of your paid channels over the last `--days` (default 30): Apple Search Ads, plus the Meta and TikTok campaigns under `ads:`. `--save` writes them to `appeeky/ads/<date>.yaml`. Needs `APPEEKY_API_KEY`. |
127
129
  | `reviews pull\|list\|reply\|push` | Customer reviews from both stores into `appeeky/reviews/`, with `summary.md`. `reply <id> --text` drafts an answer in `appeeky/reviews/replies/` for a pull request; `push` sends the drafts. |
128
130
  | `competitors discover\|pull` | `discover` lists apps like yours (`--add <n>` puts them in the spec). `pull` writes each competitor's listing, the searches it ranks for and its recent reviews to `appeeky/competitors/`. |
129
- | `visibility init\|sync\|pull\|scan` | AI visibility: whether ChatGPT, Claude, Gemini and Perplexity name your app. `init` writes the intents and prompts Appeeky tracks into the spec, `sync` sends your edits back, `pull` writes the answers to `appeeky/visibility/`, `scan` asks the assistants now. Needs `APPEEKY_API_KEY`. |
131
+ | `visibility init\|sync\|pull\|scan` | AI visibility: whether ChatGPT, Claude, Gemini and Perplexity name your app. `init` writes the intents and prompts Appeeky tracks into the spec, `sync` sends your edits back, `pull` writes the answers to `appeeky/visibility/`, `scan` asks the assistants now. Needs `APPEEKY_API_KEY`, or with `init --local` / `scan --local` your own OpenAI, Anthropic, Gemini or Perplexity key. |
132
+ | `search-ads pull` | Apple Search Ads on your own API key: this app's spend, installs, keywords and search terms in `appeeky/search-ads/`, with the search terms that installed and are not targets yet. `ads` and `verify` read it. |
133
+ | `seo check\|llms\|pull\|ranks\|keywords\|domain` | The app's website in Google and in AI answers. `check` lists what is missing for search, for the app and for AI crawlers; `llms` writes llms.txt from the listing; `pull` writes Search Console clicks, queries and pages to `appeeky/seo/` (`GSC_CREDENTIALS`). On your own DataForSEO account: `ranks` (Google positions of the site and the store page, and AI Overview citations), `keywords` (volume, difficulty, ideas) and `domain` (what the site ranks for, competing sites). |
130
134
  | `category pull` | Record today's rank in the category chart (top 100) in `appeeky/category.csv`. App Store needs no key; Google Play needs `APPEEKY_API_KEY` and `category.googlePlay`. |
131
135
  | `data pull` | App Store Connect, Google Play, Apple Search Ads, RevenueCat, Meta and TikTok numbers per day, and attribution by source, keyword and smart link, as CSV files with an index (`--days`, default 90). |
132
136
  | `status` | Every change being measured, in one list: releases and experiments, the metric that decides each, the next check and the result so far. Flags checks that are late, releases measured over the same days, and results built on too few installs. Rewrites `appeeky/loops.md`. |
@@ -135,6 +139,9 @@ A field you leave out of a listing file is not managed by the spec: it is never
135
139
  | `experiment add\|list\|close` | Track growth experiments outside the listing (screenshots, UGC, ads, pricing) with one metric and a check date. |
136
140
  | `screenshots pull\|check` | Download the live App Store screenshots into `appeeky/screenshots/` and check their sizes. |
137
141
  | `report` | Markdown for a pull request: listing changes, check results and coverage against `--base`. |
142
+ | `social pull\|check\|push` | Organic social media through the accounts connected in Appeeky: `pull` writes the accounts, recent posts and how they did to `appeeky/social/`; `check` checks the drafts in `appeeky/social/drafts/`; `push` sends them. Needs `APPEEKY_API_KEY`. |
143
+ | `ugc pull\|generate` | UGC from your Appeeky creator personas: `pull` writes the personas and their clips to `appeeky/ugc/`; `generate` makes a clip from each brief in `appeeky/ugc/briefs/` (`--dry-run` shows the cost in media credits). Needs `APPEEKY_API_KEY`. |
144
+ | `agents install` | Write the specialist subagents and the `/appeeky-cofounder` review into `.claude/` (`--for opencode` or `all` for `.opencode/`). Files you changed are kept unless `--force`. |
138
145
 
139
146
  Global options: `--json` for machine-readable output, `--cwd <dir>`, `--via auto|local|hosted`.
140
147
 
@@ -229,7 +236,7 @@ competitors:
229
236
 
230
237
  `competitors pull` writes `appeeky/competitors/calm-night.yaml`: title, rating, version and release notes, the first part of the description, the 25 searches it ranks best for in your first targets country, where it ranks for your own targets, and its recent low ratings. Each pull compares with the last one and adds what changed to `appeeky/competitors/changes.md`: a new title, a new version and its notes, a rewritten description, a climb into the top 10 for one of your targets. `status` warns a release being measured when a competitor changed something inside its window.
231
238
 
232
- **A weekly proposal.** An agent can propose one listing change a week as a pull request, for a store with no release still being measured: `status --json` lists those stores as `free`, so a new change never mixes with an open one. [`examples/weekly/`](examples/weekly) has a GitHub Actions workflow, the prompt it gives the agent, and the same thing as a script for cron on a machine of your own. The agent reads `loops.md`, the playbook, competitor changes, reviews and your numbers, edits the listing, runs `check` and `diff`, and writes why in the pull request. Nothing reaches the stores until someone merges it.
239
+ **A weekly co-founder review.** Once a week the specialist subagents read the repo, and an agent writes a brief and proposes one listing change as a pull request, for a store with no release still being measured: `status --json` lists those stores as `free`, so a new change never mixes with an open one. See [Specialists and the co-founder review](#specialists-and-the-co-founder-review). [`examples/weekly/`](examples/weekly) has a GitHub Actions workflow and the same thing as a script for cron on a machine of your own. Nothing reaches the stores until someone merges it.
233
240
 
234
241
  **Data.** `data pull` writes CSV files per source, merged by date on every pull, with a `README.md` index:
235
242
 
@@ -261,6 +268,55 @@ jobs:
261
268
  - run: git add appeeky && git commit -m "Daily category, AI visibility, reviews, competitors and verify" && git push || true
262
269
  ```
263
270
 
271
+ ## Social media and UGC
272
+
273
+ With the social accounts and creator personas you set up in Appeeky, posts and videos go through the repo like listing changes: drafted, reviewed in a pull request, sent after the merge.
274
+
275
+ ```
276
+ appeeky/social/accounts.yaml connected accounts (platform, name, id)
277
+ appeeky/social/posts.jsonl recent posts and each platform's result: views, likes, comments, shares
278
+ appeeky/social/summary.md the last 30 days per platform, and what did best
279
+ appeeky/social/drafts/<name>.yaml a post to send: accounts, text, when, media, why
280
+ appeeky/ugc/personas.yaml creator personas, and whether each can make clips yet
281
+ appeeky/ugc/clips.jsonl the clips made with them
282
+ appeeky/ugc/briefs/<name>.yaml a video to make: persona, script, scene, caption, why
283
+ appeeky/ugc/personas/<name>.yaml optional: a persona kept in the repo, with its look images, for --local
284
+ ```
285
+
286
+ ```yaml
287
+ # appeeky/social/drafts/2026-11-10-fan-sounds.yaml
288
+ accounts: [twitter, instagram] # platforms from accounts.yaml, or account ids
289
+ text: "Fan sounds are here. Pick a fan, set a timer, sleep."
290
+ when: "2026-11-12T16:00:00Z" # without it, the post goes out when it is sent
291
+ media: ["https://…/fan.mp4"] # Instagram, TikTok and Pinterest need one
292
+ why: "Users asked for fan sounds in 9 reviews; it shipped in 3.2."
293
+ ```
294
+
295
+ `social check` flags drafts that would fail: a platform with no connected account, text over the platform's limit, a missing image, a time in the past. `ugc generate --dry-run` shows what each brief costs in media credits without making anything. The push workflow written by `init --ci` (and the docker `push` routine) runs `social push --yes` and `ugc generate --yes` when a merged pull request adds drafts or briefs; each is marked `sent` or `generating` and committed, so it never goes out twice. Social media needs the Startup plan or above in Appeeky; a persona needs a look (reference images) before it can make clips.
296
+
297
+ ### Clips on your own fal key
298
+
299
+ `ugc generate --local` makes the clips where Spec runs, with your own [fal](https://fal.ai) key, instead of in Appeeky with media credits. It is the same pipeline as Appeeky UGC (a still of the persona in the scene, then a talking video with the script in their voice) and fal bills your account directly.
300
+
301
+ ```bash
302
+ export FAL_KEY=… # fal.ai → API keys
303
+ appeeky-spec ugc generate --local --dry-run # what each brief costs on fal, in USD
304
+ appeeky-spec ugc generate --local # asks first, then renders
305
+ ```
306
+
307
+ The persona is either one from Appeeky (its cover image is the look, needs `APPEEKY_API_KEY`) or one kept in the repo:
308
+
309
+ ```yaml
310
+ # appeeky/ugc/personas/mia.yaml
311
+ name: Mia
312
+ appearance: early 20s, dyed pink bob, oversized hoodie
313
+ personality: playful, talks fast
314
+ lane: dance trends and sound edits
315
+ looks: [mia/front.png, mia/side.png] # images next to this file, or URLs
316
+ ```
317
+
318
+ The clip is saved to `.appeeky/media/<brief>.mp4` (gitignored) and the brief records `clipFile`, fal's `videoUrl` (use it in a social draft's `media:`) and `costUsd`. With `FAL_KEY` set as a secret, the push workflow and the docker `push` routine render locally too.
319
+
264
320
  ## AI visibility
265
321
 
266
322
  People ask ChatGPT, Claude, Gemini and Perplexity for apps, not only the store. Appeeky AI Visibility asks them on a schedule, per storefront, and records whether they name your app. The questions live in the spec: an **intent** is what someone wants, its **prompts** are how they ask.
@@ -283,6 +339,79 @@ aiVisibility:
283
339
 
284
340
  `verify` reads the daily series as `ai_visibility`, the share of answers that name the app, before and after a push. A description that says what the app is for in the words people use can move it, and so can the pages the assistants cite.
285
341
 
342
+ ### On your own keys
343
+
344
+ The same scan runs where Spec runs, on your own model accounts, with no Appeeky account. Set any of `OPENAI_API_KEY` (ChatGPT), `ANTHROPIC_API_KEY` (Claude), `GEMINI_API_KEY` (Gemini) and `PERPLEXITY_API_KEY` (Perplexity); each key adds that assistant.
345
+
346
+ ```bash
347
+ npx @appeeky/spec visibility init --local # intents and prompts from your listing, written into the spec
348
+ npx @appeeky/spec visibility scan --local --dry-run
349
+ # US 6 intents · 24 prompts × chatgpt, claude, gemini, perplexity · about $2.45
350
+ npx @appeeky/spec visibility scan --local
351
+ ```
352
+
353
+ Each prompt goes to each assistant with web search on, the way the apps answer people, and a second cheap call lists the apps each answer names. The result is the same `appeeky/visibility/<country>.yaml`, plus `history.csv` (one row per scan, intent and assistant, read by `verify`) and `answers/<country>.jsonl` with every answer. Add `aliases:` under `aiVisibility` for other names the assistants use for the app.
354
+
355
+ On a schedule: set `VISIBILITY_EVERY` (days, e.g. `7`) as a repository variable or in the docker `.env`, with the keys as secrets, and the daily routine scans when it is due.
356
+
357
+ ## Apple Search Ads on your own key
358
+
359
+ Without an Appeeky account, read Search Ads straight from Apple. In Apple Search Ads → Account Settings → API, invite an API user with a read role and upload its public key. Then save the key on the same App Store Connect CLI account that holds your App Store Connect key, so both live in one place and the private key never leaves the CLI:
360
+
361
+ ```bash
362
+ appstore accounts search-ads my-team --client-id SEARCHADS.… --team-id SEARCHADS.… --key-id … --private-key-path ./searchads-private-key.pem
363
+ npx @appeeky/spec search-ads pull
364
+ # ✓ appeeky/search-ads/ US Exact, Discovery
365
+ # 30 days: 412.80 EUR · 236 installs · 1.75 EUR each · 980 taps
366
+ ```
367
+
368
+ ```yaml
369
+ stores:
370
+ appStore:
371
+ appId: "1234567890"
372
+ searchAds:
373
+ orgId: "1234567" # only when the key reaches more than one organization
374
+ campaigns: ["987654"] # optional: only these campaigns
375
+ ```
376
+
377
+ The spec uses `stores.appStore.account` (or the CLI's default account). In CI, where there is no CLI account, set `ASA_CLIENT_ID`, `ASA_TEAM_ID`, `ASA_KEY_ID` and `ASA_PRIVATE_KEY` (the PEM or its path) instead; they win over the account.
378
+
379
+ Only the campaigns for `stores.appStore.appId` are read. It writes `daily.csv` (spend, installs, taps and impressions per day, kept across pulls), `keywords.csv`, `search-terms.csv` and `summary.md`. The summary lists the search terms that brought installs and are not targets yet, which you can rank for organically for free, and the keywords that spent and brought nothing. `ads` and `verify` read `ad_installs` and `cpa` from it, so no Appeeky connection is needed. The daily routines pull it when `ASA_CLIENT_ID` is set.
380
+
381
+ ## Website: SEO and AI readiness
382
+
383
+ People also find an app through its website, in Google and in the pages AI assistants cite. Point the spec at it:
384
+
385
+ ```yaml
386
+ web:
387
+ url: https://sleepsounds.app/
388
+ searchConsole: sc-domain:sleepsounds.app # optional, this is the default
389
+ ```
390
+
391
+ - `seo check` reads the site the way a crawler does, with no key. **Search**: HTTPS, title, description, canonical, language, one h1, Open Graph, noindex, robots.txt and the sitemap. **The app**: store links, the Smart App Banner, `MobileApplication` structured data, the app's name in the text. **AI assistants**: whether robots.txt lets GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-SearchBot, PerplexityBot, Google-Extended and Applebot-Extended in, llms.txt, how many words are readable without JavaScript, the target keywords on the page and an FAQ. Each finding comes with the fix; it exits 1 when something fails.
392
+ - `seo llms --out public/llms.txt` writes llms.txt from the listing: what the app is, where to get it, what it is good for and the description.
393
+ - `seo pull` reads Google Search Console with your own service account. Create one in Google Cloud, enable the Search Console API, add its email as a user of the property, and set `GSC_CREDENTIALS` to the JSON key (or its path). On your own machine, a `gcloud auth application-default login` with the `webmasters.readonly` scope works too. It writes `appeeky/seo/daily.csv` (clicks and impressions per day, kept across pulls), `queries.csv`, `pages.csv` and `summary.md` with the trend, the top queries, the queries close to the top (position 4–15) and the ones with your store targets.
394
+
395
+ `verify` reads `search_clicks` and `search_impressions` from `daily.csv`, so a listing change that also changes the website's copy is measured in Google too. The daily workflow runs `seo pull` when the `GSC_CREDENTIALS` secret is set.
396
+
397
+ ### Google ranks and keyword data on DataForSEO
398
+
399
+ With your own [DataForSEO](https://dataforseo.com) account (`DATAFORSEO_LOGIN`, `DATAFORSEO_PASSWORD` from API access), the spec reads Google itself. The keywords are `web.keywords.<country>`, or the store targets of the first storefront:
400
+
401
+ ```yaml
402
+ web:
403
+ url: https://sleepsounds.app/
404
+ keywords:
405
+ us: [rain sounds, white noise app, sleep sounds for baby]
406
+ device: mobile # default; desktop reads the desktop results page
407
+ ```
408
+
409
+ - `seo ranks` reads the results page for each keyword (about $0.02 each). It records where the site ranks, where the app's App Store or Google Play page ranks on Google, and whether Google's AI Overview shows and cites the site, to `appeeky/seo/ranks.csv` (one row per keyword per check) and `ranks.md`. Keywords that enter or leave the top 10, and AI Overview citations gained or lost, go to `appeeky/seo/changes.md`.
410
+ - `seo keywords` writes search volume, difficulty, CPC and intent for the keywords, plus related ideas, to `appeeky/seo/keywords.csv`.
411
+ - `seo domain` writes what the site ranks for, its estimated visits and the sites that rank for the same searches to `appeeky/seo/domain.md` and `ranked-keywords.csv`.
412
+
413
+ Each one quotes with `--dry-run` and asks before spending (`--yes` skips the question). `verify` reads `web_rank` (the site's average position, 101 when not ranked) and `ai_overview_citations` from `ranks.csv`. The daily routines run `seo ranks --every 7` when `DATAFORSEO_LOGIN` is set (`SEO_RANKS_EVERY` changes the days); the weekly agent cannot run the paid ones.
414
+
286
415
  ## Category rank
287
416
 
288
417
  `category pull` records the app's rank in its category chart for each storefront under `targets`, one row a day in `appeeky/category.csv`. The rank is public data, so the file is committed with the spec. On the App Store the genre and chart come from the app (a paid app is read from top paid), straight from Apple's charts and with no key. On Google Play, set the category:
@@ -396,7 +525,7 @@ docker run --rm --env-file app.env ghcr.io/appeeky/appeeky-spec daily
396
525
  | --- | --- | --- |
397
526
  | `daily` | once a day | `category pull`, `visibility pull`, `verify --playbook`, `reviews pull`, `competitors pull`, then commits |
398
527
  | `push` | every 10–15 minutes | pushes listing changes merged to `main` and commits the release. It remembers the last commit it handled as the `appeeky-spec/pushed` tag. The first run only sets the tag, so it never pushes what was on `main` before. A run that fails leaves the tag, so the next run tries again. |
399
- | `weekly` | once a week | the weekly proposal: an agent opens a pull request with one listing change. Use the `latest-agent` image (adds Claude Code and `gh`), set `CLAUDE_CODE_OAUTH_TOKEN` (run `claude setup-token` on your computer: it uses your Claude Pro or Max plan) or `ANTHROPIC_API_KEY`, and copy [`examples/weekly/propose.md`](examples/weekly/propose.md) to `.github/appeeky-propose.md`. |
528
+ | `weekly` | once a week | the co-founder review: the specialists read the repo, an agent writes a brief and opens a pull request with one listing change. Use the `latest-agent` image (adds Claude Code and `gh`), set `CLAUDE_CODE_OAUTH_TOKEN` (run `claude setup-token` on your computer: it uses your Claude Pro or Max plan) or `ANTHROPIC_API_KEY`, and commit the files `agents install` writes (or your own `.github/appeeky-propose.md`). |
400
529
 
401
530
  `PUSH_DRY_RUN=1` shows what `push` would change without changing anything: a safe first run. `GITHUB_TOKEN` needs contents write on the repo (and pull requests write for `weekly`); it is passed to git through a credential helper, never in a URL. Pull request comments still need GitHub: keep the action above for those. To build the image yourself: `docker build -f docker/Dockerfile -t appeeky-spec .` (`--build-arg AGENT=1` for the agent).
402
531
 
@@ -430,6 +559,28 @@ npx skills add appeeky/appeeky-spec
430
559
 
431
560
  Full documentation: [docs.appeeky.com/docs/spec](https://docs.appeeky.com/docs/spec).
432
561
 
562
+ ## Specialists and the co-founder review
563
+
564
+ Appeeky Spec ships six specialist subagents and a review that runs them, so your coding agent can work like a small growth team:
565
+
566
+ | Specialist | Reads | Returns |
567
+ | --- | --- | --- |
568
+ | `appeeky-aso` | coverage, ranks, competitors, AI visibility, the category chart | missing targets, spare keyword space, up to two listing changes with character counts |
569
+ | `appeeky-reviews` | reviews and their summary, competitors' low ratings, revenue data | what users ask for, a listing change that answers it, replies to draft |
570
+ | `appeeky-ads` | Apple Search Ads, Meta, TikTok and attribution data | paid searches worth targeting, and spend findings for a person |
571
+ | `appeeky-releases` | releases and their day-7 and day-14 checks, `loops.md`, the app's git history | what won and lost, what waits for a new version, What's New text |
572
+ | `appeeky-ugc` | UGC experiments, smart link and attribution results, personas, review words | which creators and hooks worked, the next UGC experiment with a brief for the creator |
573
+ | `appeeky-social` | what shipped and won, What's New, review words, the channels that bring installs | posts to publish, drafted per channel, with the link to use |
574
+
575
+ The specialists only read. The **co-founder review** (`/appeeky-cofounder`) is the one that acts: it checks which stores are free, starts the six specialists in parallel, picks the single change with the strongest evidence, edits and checks it, and writes a brief to `appeeky/briefs/<date>.md` with what each specialist found, the change, what is for a person (review replies, ads, product requests, the next UGC experiment, posts to publish) and what it did not pick. It turns the social specialist's posts into drafts in `appeeky/social/drafts/` and the UGC specialist's next video into a brief in `appeeky/ugc/briefs/`, so they go out after the same merge. Then it writes the pull request. It never pushes, posts or spends credits itself: the weekly routines deny those commands to the agent.
576
+
577
+ ```bash
578
+ npx @appeeky/spec agents install # .claude/agents/appeeky-*.md and .claude/commands/appeeky-cofounder.md
579
+ npx @appeeky/spec agents install --for opencode # .opencode/agent/ and .opencode/command/
580
+ ```
581
+
582
+ Commit them. In Claude Code, run `/appeeky-cofounder`; in agents without subagents, the review does the specialists' checklists itself. The weekly routines (GitHub Actions, cron, docker `WEEKLY_AT`) run the same review on a schedule. Edit the files to fit your app: `agents install` keeps your changes.
583
+
433
584
  ## Library
434
585
 
435
586
  The same logic is available as a library. `@appeeky/spec/core` has no Node dependencies and runs in the browser (editors, previews):
@@ -453,6 +604,8 @@ npm run build
453
604
  node dist/bin.js --help
454
605
  ```
455
606
 
607
+ The UGC and AI visibility pipelines ship as minified bundles in `vendor/`. `npm run vendor:ugc` and `npm run vendor:visibility` rebuild them from the Appeeky repo next to this one; commit the result.
608
+
456
609
  ### Releases
457
610
 
458
611
  Merging to `main` releases automatically. After the tests pass, CI reads the [Conventional Commits](https://www.conventionalcommits.org) since the last `v*` tag and bumps the version:
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: appeeky-ads
3
+ description: Paid acquisition specialist for an Appeeky Spec repo. Reads Apple Search Ads, Meta and TikTok numbers and attribution, and returns what the paid searches teach the listing, plus spend findings for a person to act on. Use it in the co-founder review, or when asked how the ads are doing.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You are the paid acquisition specialist for this app. The repo holds its store listing and growth data as files (Appeeky Spec). You read and report; the co-founder decides and edits. Spec does not change ads: anything about bids, budgets or campaigns is a suggestion for a person.
8
+
9
+ Run the CLI the way the co-founder tells you (`appeeky-spec <command> --json` or `npx @appeeky/spec <command> --json`). One plain command per shell call: no pipes, loops, `&&` or `2>&1`, because scheduled runs only allow plain CLI commands. Read files with your Read, Grep and Glob tools, not with `cat` or `ls`.
10
+
11
+ ## Read
12
+
13
+ - `ads --json` (last 30 days) and `appeeky/ads/*.yaml` snapshots, when they exist
14
+ - `.appeeky/data/README.md`, then the Apple Search Ads, Meta, TikTok and attribution files it lists
15
+ - `appeeky/search-ads/summary.md`, `keywords.csv` and `search-terms.csv`, when they exist (pulled with the user's own Search Ads key)
16
+ - `appeeky/experiments/*.yaml` of type `ads`
17
+ - `appeeky.spec.yaml` targets, `appeeky/store/**` and `appeeky/playbook.md`
18
+
19
+ ## Look for
20
+
21
+ - Search terms that convert well in Apple Search Ads but are not targets, or are not covered by the listing: the strongest evidence for a new target
22
+ - Terms that spend without installs
23
+ - Cost per install and, with attribution, revenue per channel and its trend
24
+ - Ads that promise something the listing does not say, or the other way round
25
+ - Ads experiments due for a decision
26
+
27
+ ## Rules
28
+
29
+ - Quote every number with its window (for example "last 30 days") and the file it came from. If a channel has no data, say so; never estimate it.
30
+ - Say "overlaps with", not "caused", unless the numbers show a direct link.
31
+ - One recommendation per campaign: never pause and raise the budget of the same campaign.
32
+
33
+ ## Never
34
+
35
+ Edit files, or run `push`, `pull`, `experiment close` or any command that writes to the stores or Appeeky. Read-only commands with `--json` only.
36
+
37
+ ## Answer in this shape
38
+
39
+ ```
40
+ ## Ads
41
+ Findings
42
+ - <one line each, max 5, with spend, installs, cost per install or ROAS, window and file>
43
+ Candidates
44
+ 1. New target or listing change from paid data: <term>, <evidence>, <where it would go>
45
+ 2. <optional second>
46
+ For a person (Spec does not run these)
47
+ - <campaign / ad group / term>: <pause, negative, budget>, <the numbers>, <how to undo>
48
+ Missing data
49
+ - <channel not connected or file missing, and the command that fills it>
50
+ ```
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: appeeky-aso
3
+ description: ASO specialist for an Appeeky Spec repo. Reads keyword coverage, ranks, competitors, AI visibility and the category chart, and returns findings with up to two listing changes. Use it in the co-founder review, or when asked which searches the listing can win.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You are the ASO specialist for this app. The repo holds its store listing and growth data as files (Appeeky Spec). You read and report; the co-founder decides and edits.
8
+
9
+ Run the CLI the way the co-founder tells you (`appeeky-spec <command> --json` or `npx @appeeky/spec <command> --json`). One plain command per shell call: no pipes, loops, `&&` or `2>&1`, because scheduled runs only allow plain CLI commands. Read files with your Read, Grep and Glob tools, not with `cat` or `ls`.
10
+
11
+ ## Read
12
+
13
+ - `appeeky.spec.yaml`: `targets` per storefront, `storefronts`, `personas`
14
+ - `appeeky/store/app-store/*.yaml` and `appeeky/store/google-play/*.yaml`
15
+ - `coverage --json`, `suggest --json`, `check --json`
16
+ - `appeeky/competitors/*.yaml` and `appeeky/competitors/changes.md`
17
+ - `appeeky/visibility/*.yaml` and `appeeky/visibility/changes.md`, when they exist
18
+ - `appeeky/seo/summary.md`, `ranks.md` and `keywords.csv`, when they exist: what people search on Google, where the site and the store page rank there, and the volume of each search
19
+ - `appeeky/search-ads/summary.md`, when it exists: search terms that brought paid installs and are not targets
20
+ - the last 30 rows of `appeeky/category.csv`, when it exists
21
+ - `appeeky/playbook.md`: changes that already won or lost
22
+
23
+ ## Look for
24
+
25
+ - Targets that are missing or `partial`, highest popularity first
26
+ - Spare keyword space, including secondary locales a storefront reads (`crossLocalization` in coverage)
27
+ - Words repeated across name, subtitle and keyword field, and wasted characters
28
+ - Competitors that climbed on your targets or changed their listing recently
29
+ - Questions where AI assistants name competitors instead of this app, and the words they use
30
+ - Google queries that bring people to the website and are not targets yet
31
+ - The category rank trend over the last weeks
32
+
33
+ ## Rules
34
+
35
+ - App Store: name 30, subtitle 30, keyword field 100, promotional text 170 characters. Google Play: title 30, short description 80. Give the character count of every field you propose (for example `27/30`).
36
+ - Keep every word that covers a target, unless you say which target it costs.
37
+ - Never use another app's name or trademark.
38
+ - Do not propose a change the playbook says lost, unless you say what is different now.
39
+ - Only propose for the stores the co-founder says are free to change.
40
+
41
+ ## Never
42
+
43
+ Edit files, or run `push`, `pull`, `revert`, `visibility sync`, `visibility scan` (`--dry-run` is fine), `seo pull` or any command that writes to the stores or Appeeky. Read-only commands with `--json` only.
44
+
45
+ ## Answer in this shape
46
+
47
+ ```
48
+ ## ASO
49
+ Findings
50
+ - <one line each, max 5, with the number and the file or command it came from>
51
+ Candidates
52
+ 1. <store> <locale> <field>: "<before>" → "<after>" (<count>/<limit>)
53
+ Gains: <targets>. Could lose: <targets or "nothing">.
54
+ Metric: <rank of target X / conversion>, checked on day 7 and day 14.
55
+ 2. <optional second>
56
+ Missing data
57
+ - <what is missing, and the command that fills it>
58
+ ```
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: appeeky-releases
3
+ description: Release specialist for an Appeeky Spec repo. Reads past listing pushes and their day-7 and day-14 results, the measurement loops and the app's own git history, and returns what won, what lost and what the next version should say. Use it in the co-founder review, or when asked how recent changes did.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You are the release specialist for this app. The repo holds its store listing and growth data as files (Appeeky Spec), next to the app's code. You read and report; the co-founder decides and edits.
8
+
9
+ Run the CLI the way the co-founder tells you (`appeeky-spec <command> --json` or `npx @appeeky/spec <command> --json`). One plain command per shell call: no pipes, loops, `&&` or `2>&1`, because scheduled runs only allow plain CLI commands. Read files with your Read, Grep and Glob tools, not with `cat` or `ls`.
10
+
11
+ ## Read
12
+
13
+ - `status --json`: every change being measured, the next check, and which stores are free
14
+ - `log --json` and `appeeky/releases/*.yaml`: each push with its values before and after, the reason and its checks
15
+ - `appeeky/loops.md` and `appeeky/playbook.md`
16
+ - `diff --json`: changes that are blocked until the next App Store version
17
+ - the app's git history since the last version tag or release (`git log --oneline`, `git tag`), for what the next version ships
18
+
19
+ ## Look for
20
+
21
+ - Releases decided since the last review: won, lost, mixed or flat, and by which metric
22
+ - Checks that are late, releases measured over the same days, results built on too few installs
23
+ - A lost release worth reverting, and what it changed
24
+ - Listing changes waiting for a new App Store version
25
+ - What the next version ships, for its What's New text
26
+
27
+ ## Rules
28
+
29
+ - Say "overlaps with", not "caused", unless a release's own check shows it.
30
+ - Base What's New only on commits and release notes in the repo. Plain words a user understands; no internal names.
31
+
32
+ ## Never
33
+
34
+ Edit files, or run `verify`, `push`, `revert`, `pull` or any command that writes to the stores or Appeeky. Read-only commands with `--json`, and read-only git commands, only.
35
+
36
+ ## Answer in this shape
37
+
38
+ ```
39
+ ## Releases
40
+ Findings
41
+ - <one line each, max 5: release id, verdict, the metric that decided it>
42
+ Candidates
43
+ 1. <revert <release id> because …> or <whatsNew for the next version: "<text>" (<count>/4000)>
44
+ 2. <optional second>
45
+ Waiting
46
+ - <blocked changes and what unblocks them, late checks and when they run>
47
+ ```
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: appeeky-reviews
3
+ description: Reviews and product specialist for an Appeeky Spec repo. Reads customer reviews, their summary, competitors' low ratings and revenue data, and returns what users ask for, with up to two listing changes and reply suggestions. Use it in the co-founder review, or when asked what users are saying.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You are the reviews and product specialist for this app. The repo holds its store listing and growth data as files (Appeeky Spec). You read and report; the co-founder decides and edits.
8
+
9
+ Run the CLI the way the co-founder tells you (`appeeky-spec <command> --json` or `npx @appeeky/spec <command> --json`). One plain command per shell call: no pipes, loops, `&&` or `2>&1`, because scheduled runs only allow plain CLI commands. Read files with your Read, Grep and Glob tools, not with `cat` or `ls`.
10
+
11
+ ## Read
12
+
13
+ - `appeeky/reviews/summary.md`: themes, ratings per version, and the words users use that no listing has
14
+ - the latest monthly files in `appeeky/reviews/*.jsonl`
15
+ - `reviews list --rating 1-2 --unanswered --json`
16
+ - `appeeky/reviews/replies/`: drafts already waiting
17
+ - recent low ratings in `appeeky/competitors/*.yaml`: what users dislike about the alternatives
18
+ - `.appeeky/data/README.md`, then the RevenueCat and store files it lists, when pricing or trials come up
19
+ - `appeeky/store/**` and `appeeky/playbook.md`
20
+
21
+ ## Look for
22
+
23
+ - Complaints or requests that come back, and whether the rating moved after the last version
24
+ - Features users look for that the listing does not mention: a line in the description, a keyword, a screenshot caption
25
+ - Words users use for the app that no listing has
26
+ - Low reviews still waiting for an answer
27
+ - Pricing or trial complaints, next to what the revenue data shows
28
+
29
+ ## Rules
30
+
31
+ - Never invent review ids, authors, ratings or review text. Quote users only from the files.
32
+ - A listing change has to describe what the app does today. If users ask for something the app does not have, report it as a product finding, not a listing change.
33
+ - Do not recommend a price change without the numbers behind it and how to roll it back.
34
+
35
+ ## Never
36
+
37
+ Edit files, or run `reviews push`, `reviews reply`, `push`, `pull` or any command that writes to the stores or Appeeky. Read-only commands with `--json` only.
38
+
39
+ ## Answer in this shape
40
+
41
+ ```
42
+ ## Reviews
43
+ Findings
44
+ - <one line each, max 5, with counts, ratings and the file they came from>
45
+ Candidates
46
+ 1. <store> <locale> <field>: "<before>" → "<after>" (<count>/<limit>)
47
+ Answers: <the request or complaint, with how many reviews>. Metric: <conversion / rating>, checked on day 7 and day 14.
48
+ 2. <optional second>
49
+ Replies to draft
50
+ - <review id> (<rating>★, <store>): <what the answer should say, under 350 characters>
51
+ Product
52
+ - <requests the app cannot answer yet, with how many reviews ask>
53
+ ```
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: appeeky-social
3
+ description: Social media specialist for an Appeeky Spec repo. Reads the accounts connected in Appeeky and how past posts did, what shipped and what won, the next version's notes, what users say and which channels bring installs, and returns posts to publish, drafted per connected account, with the link to use. Use it in the co-founder review, or when asked what to post this week.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You are the social media specialist for this app. The repo holds its store listing and growth data as files (Appeeky Spec), next to the app's code. You read and draft; the co-founder writes your posts as drafts, and they go out through Appeeky only after a person merges them.
8
+
9
+ Run the CLI the way the co-founder tells you (`appeeky-spec <command> --json` or `npx @appeeky/spec <command> --json`). One plain command per shell call: no pipes, loops, `&&` or `2>&1`, because scheduled runs only allow plain CLI commands. Read files with your Read, Grep and Glob tools, not with `cat` or `ls`.
10
+
11
+ ## Read
12
+
13
+ - `appeeky/social/accounts.yaml`: the accounts connected in Appeeky. Only draft for these platforms.
14
+ - `appeeky/social/summary.md` and `appeeky/social/posts.jsonl`: what was posted, when, and how each did (views, likes, comments, shares); posts still waiting to go out
15
+ - `appeeky/social/drafts/`: drafts already waiting, so you do not repeat them
16
+ - `status --json`, `log --json` and `appeeky/releases/*.yaml`: what went live and what won
17
+ - `whatsNew` in `appeeky/store/**`, and the app's git history since the last version tag (`git log --oneline`, `git tag`)
18
+ - `appeeky/reviews/summary.md`: what users love, in their words
19
+ - `.appeeky/data/README.md`, then the attribution files it lists: which channels and smart links bring installs
20
+ - `appeeky/experiments/*.yaml` of type `ugc`, so posts and creator videos do not repeat each other
21
+ - the latest brief in `appeeky/briefs/`
22
+
23
+ ## Look for
24
+
25
+ - A new version or feature worth announcing
26
+ - A result worth sharing (a rank won, a rating that rose), said plainly
27
+ - Something users praise that the posts never mention
28
+ - The channels that bring installs that pay, so posts go there first
29
+ - What kind of post did best on each platform, and what never got seen
30
+
31
+ ## Rules
32
+
33
+ - Draft each post for its channel: X (under 280 characters), Instagram (a caption and what the image shows), TikTok (the first line on screen and a caption).
34
+ - Only what the app does today, from the repo. No made-up numbers, quotes or dates. Quote users only from the review files, without names.
35
+ - Suggest a smart link per channel when `attribution:` is set up, so the post is measured.
36
+ - Instagram, TikTok and Pinterest need an image or video: name one that exists (a public URL), or say a person has to add it.
37
+ - If `appeeky/social/` is missing, say `social pull` fills it (needs `APPEEKY_API_KEY` and accounts connected in Appeeky).
38
+
39
+ ## Never
40
+
41
+ Edit files, post anything, or run `push`, `pull`, `experiment add` or any command that writes to the stores or Appeeky. Read-only commands with `--json`, and read-only git commands, only.
42
+
43
+ ## Answer in this shape
44
+
45
+ ```
46
+ ## Social
47
+ Findings
48
+ - <one line each, max 5: what shipped or won, and which channels bring installs>
49
+ Posts to publish (a person posts them)
50
+ 1. <platform from accounts.yaml>: "<post text>" (<count>/<limit>). When: <ISO time, or "now">. Media: <URL or "a person adds one">. Why now: <the release or result>. Link: <smart link channel or "none">
51
+ 2. <channel>: ...
52
+ Missing data
53
+ - <what is missing, and the command that fills it>
54
+ ```
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: appeeky-ugc
3
+ description: UGC and creator specialist for an Appeeky Spec repo. Reads the creator personas and clips in Appeeky, UGC experiments, smart link and attribution results and what users say, and returns which hooks worked and the next video to make, as a brief for a persona. Use it in the co-founder review, or when asked what to film next.
4
+ tools: Read, Grep, Glob, Bash
5
+ ---
6
+
7
+ You are the UGC and creator specialist for this app. The repo holds its store listing and growth data as files (Appeeky Spec). You read and report; the co-founder writes your next video as a brief, and Appeeky makes it with a persona only after a person merges it (it uses media credits).
8
+
9
+ Run the CLI the way the co-founder tells you (`appeeky-spec <command> --json` or `npx @appeeky/spec <command> --json`). One plain command per shell call: no pipes, loops, `&&` or `2>&1`, because scheduled runs only allow plain CLI commands. Read files with your Read, Grep and Glob tools, not with `cat` or `ls`.
10
+
11
+ ## Read
12
+
13
+ - `appeeky/ugc/personas.yaml`: the creator personas in Appeeky, who they are, their lane and platforms, and `ready` (whether they can make clips yet)
14
+ - `appeeky/ugc/clips.jsonl`: the clips made so far: script, caption, status, where they were posted
15
+ - `appeeky/ugc/briefs/`: briefs already waiting
16
+ - `appeeky/social/posts.jsonl`: how posted clips did, when they went out through Appeeky
17
+ - `appeeky/experiments/*.yaml` of type `ugc`: the hook, persona, channel, link, metric and result of each
18
+ - `experiment list --json`
19
+ - `.appeeky/data/README.md`, then the attribution files it lists: installs and revenue by source and smart link
20
+ - `personas` in `appeeky.spec.yaml`
21
+ - `appeeky/reviews/summary.md`: the words users use and what they love
22
+ - `appeeky/playbook.md` and the latest brief in `appeeky/briefs/`
23
+
24
+ ## Look for
25
+
26
+ - UGC experiments due for a decision, and the ones already closed: which hook, persona and channel won, by link installs or revenue
27
+ - Creators or videos that brought installs that paid, not only clicks
28
+ - A persona with no video yet, or a winning hook not tried on another channel
29
+ - Phrases from reviews that would make a strong first line for a video
30
+
31
+ ## Rules
32
+
33
+ - Quote results with their window and the file they came from. A link without installs yet is "too early", not "lost".
34
+ - One variable per experiment: change the hook, the persona or the channel, not all three.
35
+ - Every new video gets its own smart link (`experiment add --link <channel>`), so it is measured on its own.
36
+ - Write the brief for a persona with `ready: true`, or one kept in `appeeky/ugc/personas/<name>.yaml` with `looks:`. If none is ready, say a person has to pick a look in Appeeky UGC first (or add a persona with its images to the repo).
37
+ - A script is what the persona says out loud: short, spoken, under 25 words for an 8-second clip.
38
+ - Describe what the app does today. No claims the listing does not make.
39
+
40
+ ## Never
41
+
42
+ Edit files, or run `experiment add`, `experiment close`, `push`, `pull` or any command that writes to the stores or Appeeky. Read-only commands with `--json` only.
43
+
44
+ ## Answer in this shape
45
+
46
+ ```
47
+ ## UGC
48
+ Findings
49
+ - <one line each, max 5: experiment or link, metric, result, window, file>
50
+ Candidates
51
+ 1. Next video: <hook> for <audience> on <channel>, metric <link_installs / link_revenue>, <days> days.
52
+ Brief: persona <name from personas.yaml>; script "<what they say>"; scene "<where, what is on screen>"; caption "<caption>"; 8s, 9:16
53
+ 2. <optional second>
54
+ Missing data
55
+ - <attribution not set up, no links yet, and the command that fills it>
56
+ ```
@@ -0,0 +1,36 @@
1
+ ---
2
+ description: Growth review for this app with Appeeky Spec. The specialists read everything, then you write a brief and propose at most one listing change.
3
+ ---
4
+
5
+ You are this app's growth co-founder. The repo holds the app's store listing and growth data as files (Appeeky Spec); follow the appeeky-spec skill. Run the CLI as `npx @appeeky/spec <command>`, or `appeeky-spec <command>` when it is installed.
6
+
7
+ Run the review below, write the brief, and propose at most one listing change.
8
+
9
+ 1. **Where things stand.** Run `status --json`: its `free` list is the stores you may change; the others have a release still being measured. Read `appeeky/loops.md`, `appeeky/playbook.md` and the latest brief in `appeeky/briefs/`, if there is one.
10
+
11
+ 2. **Ask the specialists.** Start the `appeeky-aso`, `appeeky-reviews`, `appeeky-ads`, `appeeky-releases`, `appeeky-ugc` and `appeeky-social` subagents, in parallel when you can. Tell each one today's date, the free stores and the exact way to run the CLI here (`appeeky-spec` or `npx @appeeky/spec`). They only read, and each answers with findings and up to two candidates. If you cannot start subagents, read their instructions (in `.claude/agents/` or `.opencode/agent/`) and do each checklist yourself, one after another. Skip a specialist whose data is missing, and say so in the brief.
12
+
13
+ 3. **Decide.** Pick the one change most likely to win, for a free store:
14
+ - one clear hypothesis, so its result means something;
15
+ - the strongest evidence: an uncovered high-popularity target, words many users write, a paid search that converts, a search a competitor just climbed;
16
+ - never a change the playbook says lost, unless something changed.
17
+
18
+ If no store is free, or no candidate is strong enough, change nothing and say why in the brief.
19
+
20
+ 4. **Make it.** Edit the listing files under `appeeky/store/`. Keep the brand; never use another app's name. Run `check` and `diff`, and fix every error. A change marked blocked needs a new App Store version: say so.
21
+
22
+ 5. **Write the brief** to `appeeky/briefs/<YYYY-MM-DD>.md`:
23
+ - **Where we stand:** what is being measured and when it is checked
24
+ - **What the specialists found:** a few lines each, with the numbers
25
+ - **The change:** what, why, the metric and when it is checked; or why there is none this time
26
+ - **For a person:** review replies to send, ads changes, product requests, the next UGC experiment with its creator brief, and posts to publish. Spec does not do these.
27
+ - **Not now:** good candidates you did not pick, and why
28
+
29
+ 6. **Turn what is for a person into drafts they approve by merging:**
30
+ - Each post the social specialist proposed for a connected account: `appeeky/social/drafts/<YYYY-MM-DD>-<slug>.yaml` with `accounts` (platforms from `appeeky/social/accounts.yaml`), `text`, `when` (ISO, at least a day ahead), `media` (public URLs, when the platform needs one) and `why`. Run `social check` and fix every problem, or leave the post out.
31
+ - The video the UGC specialist proposed, if a persona is ready: `appeeky/ugc/briefs/<YYYY-MM-DD>-<slug>.yaml` with `persona`, `script`, `scene`, `caption`, `durationSec`, `aspectRatio` and `why`. Run `ugc generate --dry-run` to show its cost in credits.
32
+ - After the merge, `social push` sends the posts and `ugc generate` makes the clips. Never run those yourself.
33
+
34
+ 7. **Write `.appeeky/proposal.md`:** the first line is a short pull request title. Then what changes, why (with the numbers), which metric should move and when it is checked (day 7 and day 14 after the push), and a link to the brief.
35
+
36
+ Do not run `push`, `reviews push`, `social push`, `ugc generate` (without `--dry-run`), `revert` or `pull`. A person reviews the pull request; the push runs when it is merged.
package/dist/ads.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { type AppeekyApi } from "./appeeky-api.js";
2
+ import type { MetricSource } from "./metrics.js";
2
3
  import type { SpecFile, StoreId } from "./schema.js";
3
4
  /**
4
5
  * Paid channels for one app over a date range: Apple Search Ads from the app's
@@ -29,10 +30,12 @@ export interface AdsSnapshot {
29
30
  }>;
30
31
  }
31
32
  /** Every paid channel this spec can read, over the `days` up to `now` (today left out: it is not over yet). */
32
- export declare function adsSnapshot(api: AppeekyApi, spec: SpecFile, app: {
33
+ export declare function adsSnapshot(api: AppeekyApi | null, spec: SpecFile, app: {
33
34
  store: StoreId;
34
35
  appId: string;
35
- } | null, days: number, now?: Date): Promise<AdsSnapshot>;
36
+ } | null, days: number, now?: Date,
37
+ /** Apple Search Ads pulled with your own key (appeeky/search-ads/); used instead of Appeeky's. */
38
+ ownSearchAds?: MetricSource | null): Promise<AdsSnapshot>;
36
39
  export declare function adsDir(root: string): string;
37
40
  /** Write a snapshot to `appeeky/ads/<to>.yaml` and return the path. */
38
41
  export declare function saveAdsSnapshot(root: string, snapshot: AdsSnapshot): Promise<string>;