Install
$ agentstack add skill-mr-kelly-skills-kelly-ads ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Kelly Ads
Overview
Use this skill as Kelly's ad-campaign command desk. It aggregates spend and performance from Amazon Ads, Meta (FB/IG), TikTok Ads, and Google Ads into one file-backed App-in-Skill board (spend, impressions, clicks, conversions, revenue, ROAS, ACOS per campaign), detects anomalies deterministically (ACOS above target for N days, budget exhausted before day end, high-spend zero-conversion search terms/creatives, sudden CPC spikes, paused/rejected campaigns), and turns them into agent-proposed adjustment cards with evidence and expected impact. The human approves; the agent executes approved adjustments outside the app via the platform APIs.
Default interaction mode: App UI. Unless the user explicitly asks for chat-only handling, check onboarding/config, refresh the ads snapshot with the ingest/check scripts, start/reuse the local app with app/start.sh, and give the actual local URL. Use chat-only mode only when the user says "纯聊天", "chat only", "不要打开 UI", or similar; then present numbered adjustment cards (Adjustment #1) and take verdicts in chat.
App UI Screenshots
OverviewCross-platform ads board: blended ROAS/ACOS vs target, per-platform cards, spend vs revenue bars, and worst offenders. CampaignsCampaign table with budget pace, spend, ROAS, and color-coded ACOS vs target across Amazon, Meta, TikTok, and Google.
Adjustment queueAgent-proposed bid, budget, and negative-keyword changes with evidence and expected impact, gated on approval. AlertsDeterministic anomaly feed: ACOS breaches, budget burnouts, zero-conversion spend, CPC spikes, rejected ads.
Boundary
- Report ingestion is read-only: the agent pulls platform reports (API pulls, report exports, or pasted CSVs) outside the app and feeds them to
scripts/ingest_reports.ts. Nothing in this skill mutates a platform on its own. - The app reads and writes local files only. It must not call platform APIs, change bids, budgets, keywords, or creatives, or touch any network beyond
127.0.0.1in the defaultlocaldata provider. The optional, explicitly-configuredbusabasedata provider (KELLY_ADS_DATA_PROVIDER=busabase/config.busabase.base_url) is the sole exception: it talks to a Busabase base the user has configured, using the same review-provider pattern documented across this repo's App-in-Skills. It is never enabled by onboarding or by default. - Every bid/budget/keyword/creative mutation is approval-required and executed by the agent outside the app, only after the matching adjustment card is
approved.scripts/execute_decisions.tsis a dry-run planner, never an executor. - Ad account credentials live only in local env files referenced by name from private config (
*_envkeys). Never store tokens in the repo or paste them into chat. - Do not commit
config.local.json, env files,app/.data/, report exports, or raw platform responses.
First Run And Onboarding
On invocation, check app/.data/onboarding.json and private config readiness. If onboarding is absent/incomplete, guide setup before ingesting real data.
Private config priority:
KELLY_ADS_CONFIG=/absolute/path/to/config.jsonskills/kelly-ads/config.local.json~/.config/kelly-ads/config.jsonskills/kelly-ads/config.example.jsonas template only
Env priority:
- Existing environment variables
KELLY_ADS_ENV_FILE=/absolute/path/to/.env- Repository root
.env skills/kelly-ads/.env.local~/.config/kelly-ads/.env
Onboarding asks, turn by turn: which platforms are live and their display-safe account ids (Amazon entity/profile, Meta act_…, TikTok advertiser id, Google customer id), which env var names hold the tokens, ACOS/ROAS targets (default plus per-platform or per-product overrides), anomaly thresholds (breach days, zero-conversion spend floor, CPC spike %, budget pace), and the base currency plus rates for any other report currencies. Ask for non-secret details only; secrets go into local env files, never chat.
When setup is complete and the user confirms, write app/.data/onboarding.json:
{
"completed": true,
"completed_at": "ISO timestamp",
"config_version": "1"
}
Local App
Start the command desk with:
skills/kelly-ads/app/start.sh
The app uses local HTTP on 127.0.0.1, preferring port 3000 through 4000, or KELLY_ADS_UI_PORT when set. /api/state reports app: "kelly-ads".
Required app views:
#/overview: ads command desk. Human-attention panel (adjustments to approve, critical anomalies, budget at risk today), KPI cards (spend MTD vs last month, blended ROAS, blended ACOS vs target, conversions), per-platform mini-cards with badges, a 14-day spend-vs-revenue daily bar chart (inline SVG, no chart library), a worst-offenders list (highest-spend zero-conversion targets), data freshness per platform, and recent sync activity.#/campaignsand#/campaigns/: campaign table with name, platform badge, product/SKU, status (active/paused/rejected), daily budget + % spent today, spend 7d, ROAS, ACOS vs target (color-coded), and trend arrow. Detail shows the daily spend/ROAS series (inline SVG), the search terms/audiences/creatives table with per-row metrics, linked anomalies, and adjustment history.#/alerts: anomaly feed with severity badge, type badge (acosbreach/budgetexhausted/zeroconversionspend/cpc_spike/rejected), campaign + platform, one-line evidence, age, state (open/actioned/dismissed/resolved), and a link to the adjustment card when one exists.#/adjustmentsand#/adjustments/: the review queue with workflow statesneeds_review,changes_requested,approved,done,blocked. Each card shows a stable ref (Adjustment #1), type badge (negativekeyword/biddown/bidup/pausetarget/budgetshift/creativerefresh), target, current → proposed value, reason with evidence, expected impact, an editableReview note, and decision buttons (approve / request changes / block).donemeans executed, backed by an execution record. Decisions are rejected with HTTP 423 whileagent.lockexists.#/settings: sanitized config summary. Platforms with display-safe account ids and token*_envreadiness booleans, ACOS/ROAS targets, anomaly thresholds, currency, data provider name, and onboarding state. Never expose secret values.
Demo mode:
?demo=1opens a deterministic mock command desk for documentation and screenshots.?demo=overview,?demo=campaigns,?demo=alerts,?demo=adjustments, and?demo=detailselect named mock scenes (persona: "Nimbus Home", a home/kitchen gadget seller).lang=enorlang=zhforces UI chrome language; withlang=zhthe demo reasons, evidence, impact estimates, and summaries are meaningfully localized for Chinese screenshots (campaign names may keep English product names).- Demo API responses never read or write files under
app/.data/, and demo decisions are never persisted.
UI language: support English and Chinese chrome with Auto default. Keep campaign names, search terms, SKUs, and platform data in their original language.
File Contract
Read references/ads-schema.md before editing the app, scripts, or any generated ads JSON.
Primary local files:
app/.data/ads_snapshot.json: canonical snapshot (platforms, campaigns with daily series and targets, anomalies, adjustments, metrics, sync_log).app/.data/decisions.json: user verdicts keyed by adjustment id.app/.data/agent_tasks.json: queued agent work fromrequest_changesverdicts. Poll this to pick up revisions.app/.data/execution_report.json: planned operations fromexecute_decisions.ts(dry-run, handoff to agent).app/.data/onboarding.json: onboarding completion marker.app/.data/agent.lock: temporary lock while the skill ingests/checks/rewrites files; the adjustments queue honors it (HTTP 423 on POST while locked).config.local.json: private platform configuration, ignored by git.
Use scripts/validate_ui_schema.ts app/.data/ads_snapshot.json before relying on a snapshot in the UI. The app shows an empty setup state when no snapshot exists.
Sync Workflow
Data collection is agent-driven on invocation — there is NO cron and the app never fetches anything itself.
- Detect mode. Default to App UI.
- Load private config through the store helpers. If only
config.example.jsonexists, enter onboarding. - When the user asks for fresh numbers (or the snapshot is stale), gather report data per platform outside the app: pull via the platform reporting APIs with the configured credentials, download report exports, or accept a CSV the user pasted/dropped.
- Feed everything through the single write path:
node scripts/ingest_reports.ts payload.json— normalized JSON performance payload (shape documented in the script header).node scripts/ingest_reports.ts --csv report.csv --platform amazon [--campaign ]— raw platform CSV export, columns mapped viaconfig.csv_mappings.; the built-in parser handles quoted fields with embedded commas.- The script validates, converts currencies via
config.currency_rates, merges daily series by campaign+date (idempotent re-ingest), updates platform freshness, and appends the sync log.
- Every script acquires
app/.data/agent.lockbefore writing and releases it after; scripts refuse to run over a foreign lock. - Validate the snapshot, start/reuse the UI, and report the URL plus what needs a decision.
Check Workflow
- After ingest, run
node scripts/run_checks.ts. It reads thresholds from config and detects, deterministically:
acos_breach: campaign ACOS above target for N consecutive spend days (thresholds.acos_breach_days).budget_exhausted: daily budget spent tothresholds.budget_exhausted_pctbefore day end.zero_conversion_spend: an enabled target at or abovethresholds.zero_conversion_spend_floorin 14-day spend with 0 conversions.cpc_spike: latest-day CPC at leastthresholds.cpc_spike_pctabove the trailing mean.rejected: campaign or creative rejected by the platform.
- Anomalies are upserted with stable ids: re-detection refreshes evidence, cleared conditions auto-resolve,
dismissedstays dismissed. Re-running without data changes is idempotent. - New critical anomalies without a linked card get a skeleton adjustment card (
needs_review). Enrich each skeleton before asking for approval: re-ingest with better evidence, write the concretecurrent_value→proposed_value, and a numericexpected_impact.
Adjustment Workflow
- The user reviews adjustment cards in
#/adjustments(or byAdjustment #Nin chat) and gives verdicts: approve, request changes (with a note), or block. Notes save todecisions.jsonand the snapshot. request_changesenqueues the card inapp/.data/agent_tasks.json. Poll it, revise the card (new evidence, resized proposal), set it back toneeds_review, and clear the task.- For approved cards, run
node scripts/execute_decisions.tsto writeexecution_report.jsonwith concrete planned operations (add_negative_keywordwith term + campaign id,set_bidcurrent → new,pause_target,shift_budgetfrom → to,refresh_creative) — alldry_run: trueandhandoff_to_agent: true, no external side effects. - Re-read decisions immediately before executing. Execute approved operations outside the app via the platform APIs with the user's credentials, then mark the card
donein the snapshot with anexecutionrecord and append a sync-log entry. - If a target is missing (no account id, no term text, no destination campaign), block and ask for configuration instead of guessing.
Safety Defaults
- Treat every bid change, budget change, keyword/negative change, pause/enable, and creative swap as approval-required; anything spending money is never automatic.
- Prefer read-only reporting scopes for tokens where the platform offers them.
- Redact tokens and token-like strings in logs, reports, and UI state; expose only env-var readiness booleans and display-safe account ids.
- Keep stable ids (
campaign_id,target_id,anomaly_id,adjustment_id,ref) so repeated ingests, checks, and executions are idempotent. - If report numbers look inconsistent (spend without impressions, revenue with zero conversions), surface a warning and ask; do not invent corrections.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mr-kelly
- Source: mr-kelly/skills
- License: MIT
- Homepage: https://mr-kelly.github.io/skills/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.