Preview every change before it goes live. Commit. Roll back with git.
$ ads plan + campaign/brand-search create + campaign/brand-search/core-kw create + campaign/brand-search/core-kw/rsa create ~ campaign/retarget/budget $20 → $35/day ~ campaign/retarget/broad-match/rsa +3 headlines - campaign/old-spring-promo delete 3 to create · 2 to update · 1 to delete Run `ads apply` to execute.
You've been clicking through the platform UI for 40 minutes making a budget change — only to realize you applied it to the wrong campaign.
There's no preview, no audit trail, and no way to review changes before they go live. Mistakes cost money.
Roll back? Copy the settings from memory, hope you got them right.
Meanwhile the platform is drifting away from what you think it is.
Run `ads plan` to diff your TypeScript campaign definitions against live platform state. Every create, update, and delete is listed before a single API call is made.
$ ads plan + campaign/brand-search create + campaign/brand-search/core-kw create ~ campaign/retarget/budget $20 → $35/day - campaign/old-spring-promo delete 2 to create · 1 to update · 1 to delete
Mutations execute in dependency order: campaign → ad group → keyword → ad. Deletes go child-first. A failure stops execution immediately to avoid orphaned resources.
$ ads apply Creating campaign/brand-search... ✓ Creating campaign/brand-search/core-kw... ✓ Updating campaign/retarget/budget... ✓ $20 → $35 Deleting campaign/old-spring-promo... ✓ Applied 4 changes in 1.8s.
Someone changed a bid on the platform UI. `ads pull` detects the drift between your TypeScript definitions and live state so you can decide whether to re-apply or update your source.
$ ads pull ~ campaign/brand-search/budget $40/day → $55/day (platform ahead) ~ campaign/retarget/rsa final_url changed (platform ahead) 2 resources drifted. Run `ads plan` to re-apply.
Full diff of creates, updates, and deletes before any API call is made.
Campaigns before ad groups before keywords before ads. Deletes are reversed.
Failures stop execution immediately. Revert with git and re-apply.
Pull live state and see what diverged from your source definitions.
Every apply is logged to a local SQLite cache with timestamps and diffs.
`ads plan` never writes. Use it in CI to validate before merging.