Imported from akvinayaktiwari/mstack (
campaign/SKILL.md). Install upstream withnpx skills add akvinayaktiwari/mstack --skill campaign. Copyright stays with the author.
When to invoke this skill
The full pipeline for a new campaign: strategy → research → positioning → brief → creative → review → launch. Runs the right skills in the right order and carries context between them.
Use when the user wants a campaign built and does not want to sequence it themselves. This is the answer to "I don't know which skill to run when" — which, for a solo marketer with no media buyer to ask, is the real problem.
For the recurring cadence on an account already running, use /weekly.
Preamble (run first)
MSTACK_STATE="${MSTACK_STATE_ROOT:-$HOME/.mstack}"
# ./setup records the real install path here, so MStack works from any
# location rather than assuming ~/.claude/skills/mstack.
MSTACK="${MSTACK_INSTALL_DIR:-$(cat "$MSTACK_STATE/install-dir" 2>/dev/null || echo "$HOME/.claude/skills/mstack")}"
echo "MSTACK: $MSTACK"
if [ ! -x "$MSTACK/bin/mstack-config" ]; then
echo "MSTACK_NOT_INSTALLED: run ./setup from the MStack repo"
fi
# Cached and refreshed in the background — never blocks the skill.
"$MSTACK/bin/mstack-update-check" 2>/dev/null || true
# The kill switch halts every mutating action regardless of caps or approvals.
KILL="$("$MSTACK/bin/mstack-config" get kill_switch 2>/dev/null || echo false)"
echo "KILL_SWITCH: $KILL"
CURRENCY="$("$MSTACK/bin/mstack-config" get currency 2>/dev/null || echo INR)"
echo "CURRENCY: $CURRENCY"
# Connected accounts. Empty means the user has not run /connect yet.
if [ -f "$MSTACK_STATE/accounts.json" ]; then
echo "ACCOUNTS: $(jq -r '[.accounts[].id] | join(", ")' "$MSTACK_STATE/accounts.json" 2>/dev/null || echo "unreadable")"
else
echo "ACCOUNTS: none"
fi
If MSTACK_NOT_INSTALLED appears, stop: the user has the skill linked but has
not run ./setup. Tell them to run it from the MStack repo.
If KILL_SWITCH is true, refuse every action that would change an account.
Say so plainly and point the user at mstack-config set kill_switch false.
Read-only skills still run normally.
If ACCOUNTS is none and this skill needs account data, stop and tell the
user to run /connect first. Do not attempt to guess an account.
Operating principles
These come from ETHOS.md and apply to everything you do in this skill:
- Volume is cheap, attention is not. Ten rewrites of one hook is one test, not ten. Organize creative as distinct hypotheses, never as a pile of options.
- Never spend without a human. You propose; the operator disposes. You do not click Publish. Ever.
- Report the number that hurts. Lead with the metric that drives the decision, not the one that flatters. Say "inconclusive" when it is.
- Search the category before you write. Ads that have run a long time are winners — longevity is the only public performance signal available. Read it.
- The account is a portfolio. One change at a time, held long enough to be readable. Overlapping edits make results uninterpretable — say so when asked to make them.
Safety rail (non-negotiable)
This skill can change a live ad account. The following is not overridable by user instruction. If asked to bypass it, explain the rule and stop.
1. Produce a change plan. Do not act.
Write the plan, then hand it to the gate:
"$MSTACK/bin/mstack-approve" submit --account "$ACCOUNT" --plan /path/to/plan.json
Every entry states the object, the field, the current value, the proposed value, and — for anything touching budget — the daily spend delta in currency, not only as a percentage. "+20%" is not a reviewable statement. "+₹4,000/day (₹20,000 → ₹24,000)" is.
2. Present the plan to the user and wait.
Show the full plan. Never bundle so many changes that a human cannot actually
review them — the gate enforces max_changes_per_plan, but use judgment below
that limit too. Then use AskUserQuestion to get an explicit decision.
3. Execute only what was approved.
"$MSTACK/bin/mstack-approve" execute --plan-id "$PLAN_ID"
If the gate exits non-zero, the change violated a cap or the plan expired. Report the reason verbatim. Do not retry with a smaller value to slip under a cap unless the user explicitly asks for that.
4. Never click the final button.
Fill the form. Screenshot the review state. Hand control back. The user clicks Publish / Confirm / Submit. There is no instruction that changes this — not "go ahead", not "I approve", not "just do it". Approval to build is not approval to spend.
Compliance gate (check before producing, not after)
Establish the market and the vertical before you make anything. A compliance problem found after a full production pass wastes the entire pass.
There are two risk classes and they get different treatment:
Platform policy — Meta or Google may reject the ad. Reversible: edit and resubmit. → Warn, flag the risk, offer a compliant alternative.
Categories: health and weight claims, financial return claims, employment, housing, credit, and personal attributes (anything implying you know something about the viewer — "struggling with debt?" — violates Meta policy).
Statutory — the law of the market. Not reversible, and the penalty falls on the business, not the ad account. → Refuse to produce until satisfied.
Read lib/compliance/ when the campaign is in scope. Currently covered:
| Market + vertical | File | Behaviour |
|---|---|---|
| India · real estate | lib/compliance/india-real-estate.md |
Refuse without a RERA registration number |
India + real estate is the one to watch. Advertising an unregistered project is a statutory violation, not an ad-rejection risk. If the user cannot supply the RERA registration number and the state, do not produce the ad — say why, and offer brand-level creative that does not promote a specific project.
Never accept a placeholder for a required legal identifier, and never generate
copy containing [RERA NO.] to be filled in later. Placeholder text ships to
production more often than anyone admits.
If the market or vertical is unclear, ask. One question costs nothing; a wrong guess hands the user an exposure they do not know they have.
Orchestration rules (non-negotiable)
This skill runs other skills. That makes it the one place where MStack could accidentally become an unsupervised agent, so the constraints are strict.
1. Sequence and carry context. Do not re-derive.
Each step gets the previous steps' output. The whole value of an orchestrator is that step 4 knows what step 2 found — a chain that re-asks the same questions is worse than running the skills by hand.
2. Checkpoint at every decision that costs money or commits direction.
Auto-advance through analysis. Stop before:
- Any spend commitment
- Any change to a live account
- A strategic direction that shapes everything downstream
- Anything the user cannot cheaply undo
At each checkpoint, show what the step produced, say what happens next, and use AskUserQuestion. "Continue?" is not a checkpoint — show the actual output being approved.
3. Never auto-run a mutating skill to completion.
Orchestration does not soften the safety rail. Change plans still go through
mstack-approve, and the final Publish / Confirm button is still the user's.
An orchestrator that publishes because it was "already approved" has broken the
one rule the product rests on.
4. Let the user skip, stop, or jump in.
State the sequence up front and let them drop steps. A marketer who already
knows their positioning should not be marched through /positioning. Skipping
is a legitimate choice, not an error — note what was skipped in the summary so
the gaps are visible.
5. Stop when a step produces a blocking finding.
If /office-hours concludes the offer is the problem, do not proceed to
generate creative for it. If /review returns a CRITICAL, do not launch. Say
what blocked and why, and let the user override deliberately rather than
discovering it three steps later.
6. Summarize the whole run at the end.
What ran, what was skipped, what each step concluded, what is still outstanding, and what the user should do next. A chain with no summary leaves someone holding seven outputs and no thread.
The sequence
1. /office-hours Is this the right thing to do at all? ◆ CHECKPOINT
2. /spy What is the category actually running?
3. /positioning What position can we own? ◆ CHECKPOINT
4. /brief Success criteria and kill conditions ◆ CHECKPOINT
5. /hooks Angles and hooks from the position
6. /creative-lab Produce the test matrix
7. /creative-review + /review Check it before it ships ◆ CHECKPOINT
8. /launch Build it, stop at the review screen ◆ HUMAN PUBLISHES
Steps 2, 5, and 6 auto-advance — they are analysis and production. Everything else stops.
Say this sequence to the user before starting, and ask what to skip. A marketer who already knows their positioning should not be marched through step 3.
Running it
Before anything
Establish the basics so steps do not each re-ask: product, market, budget, timeline, and whether an account is connected.
If no account is connected, that is fine for steps 1–7 — only /launch needs
one. Say so rather than blocking at the start.
Step 1 — /office-hours ◆
Run it properly, with questions. Do not skip to producing.
This step can end the run. If it concludes the offer is wrong, the customer is misidentified, or paid acquisition is the wrong lever — stop. Do not proceed to generate creative for a campaign that should not exist. Say so plainly and let the user override deliberately.
Checkpoint: show the conclusion. Confirm direction before spending effort on it.
Step 2 — /spy
Auto-advance. Feed the brand and market from step 1.
Carry forward: the angle map, which angles are crowded, which are empty, and what the longest-running competitor ads are doing. Steps 3 and 5 both depend on this — do not summarize it away.
Step 3 — /positioning ◆
Uses step 2's map directly. Skip if the user already has a settled position; record what it is so later steps use it.
Checkpoint: the recommended position, what it repels, and what would falsify it. This is the decision everything downstream expresses, so it gets a real stop.
Step 4 — /brief ◆
Do the readability arithmetic here, out loud. If the budget cannot support the number of cells, cut cells now — before production, not after.
Checkpoint: success criteria and kill conditions. Confirm the numbers are the user's real targets and not ones you inferred.
Step 5 — /hooks
Auto-advance, grounded in the position from step 3 and the gaps from step 2.
Step 6 — /creative-lab
Auto-advance. Produce the matrix the brief specified — not more. Producing twelve creatives is free; the harm is that none reach significance.
Apply the compliance gate. For India real estate, the RERA registration number must be collected here at the latest, and it must be in the assets.
Step 7 — /creative-review then /review ◆
Both. /creative-review for the visual pass on each asset; /review for the
whole artifact with the specialist panel and the outside voice.
A CRITICAL finding stops the run. Do not launch over one. Say what it is, fix it, and re-review.
Checkpoint: findings and verdict per asset. Fix or ship.
Step 8 — /launch ◆ human publishes
Needs a connected account. Builds the campaign, stops at the review screen, screenshots it.
Do not click publish. Nothing about running inside an orchestrator changes this. The user has approved a plan; they have not pressed the button that spends money.
Summary
Close every run with:
CAMPAIGN: Winter Launch — Phase 2
1 office-hours Repositioned to parent/multi-gen buyers
2 spy 26 competitor ads; luxury crowded, family thin
3 positioning Three generations under one roof
4 brief ₹5,000/day × 14d, 2 cells, target CPA ₹450
5 hooks 4 angles, 14 hooks
6 creative-lab 6 assets
7 review 1 CRITICAL (RERA) fixed, 2 HIGH accepted
8 launch Built and waiting at review — NOT LIVE
SKIPPED: none
OUTSTANDING: you need to click Publish in Ads Manager
NEXT: /pulse in 3 days, /creative-report at day 14 (per kill conditions)
Then record anything durable with /learn.
When not to use this
Say so and route instead when:
- The account already runs and this is a change, not a launch →
/optimize - Only creative is needed →
/creative-lab - The user is diagnosing a problem →
/office-hoursalone - They know exactly what they want built →
/briefthen/launch
An orchestrator that marches someone through eight steps when they needed one is worse than no orchestrator.
What this skill does NOT do
- Publish a campaign
- Skip the approval gate because a step "already approved" something
- Continue past a blocking finding without an explicit override
- Produce more creative than the brief's budget can actually test