Skip to content

bidsmith refresh

refresh pulls the live Google Ads account into .bid files. It’s how you adopt bidsmith without rewriting your account by hand, and how you re-sync after somebody edits the UI directly. It has two modes:

  • Bootstrap (-d / -o / stdout) writes a clean snapshot of the live account as fmt-canonical .bid files, overwriting its output. This is how you start a project from an existing account.
  • Reconcile (--in-place) updates .bid files you already maintain: it finds the fields that drifted live and writes the new values back into your existing files, leaving comments, layout, and everything bidsmith doesn’t manage untouched.

Synopsis

Terminal window
bidsmith refresh [--output FILE | --dir DIR] [--include-removed] [--verbose]
bidsmith refresh --in-place [PATH] [--check] [--var NAME=VALUE] [--verbose]

Flags

FlagDescription
-o, --output FILEBootstrap: write everything to a single .bid file. Mutually exclusive with --dir.
-d, --dir DIRBootstrap: split the output into <DIR>/account.bid and <DIR>/campaigns.bid. Mutually exclusive with --output.
--in-placeReconcile: update the existing .bid files at PATH (default .) in place instead of writing fresh output. Mutually exclusive with -o / -d.
--checkWith --in-place: print what would change and write nothing.
--var NAME=VALUEWith --in-place: set a variable value. Repeatable. Same as plan.
--include-removedInclude resources whose status is REMOVED. Default: drop them. (Bootstrap only.)
--verbosePrint the outgoing API request envelope and raw response.

In bootstrap mode, if neither -o nor -d is given, output goes to stdout.

Environment variables

Same as bidsmith plan.

Exit codes

CodeMeaning
0Successful refresh.
1Authentication failure, API error, file write error, or other.

Examples

Terminal window
bidsmith refresh

Dumps the current state as a single block of .bid text. Useful for piping into another tool or eyeballing what’s there.

Write to one file

Terminal window
bidsmith refresh -o reality.bid

Single file with everything. Works well for small accounts.

Split into account- and campaign-scoped files

Terminal window
bidsmith refresh -d ads-bid/

Creates two files:

  • ads-bid/account.bid — the provider block, conversion actions, shared sets, call assets, customer assets.
  • ads-bid/campaigns.bid — campaigns, budgets, ad groups, ads, ad-group and campaign criteria.

This is the recommended pattern for accounts with more than a handful of campaigns.

Capture drift before fixing it

Terminal window
bidsmith refresh -o reality.bid
git diff reality.bid summer-2026.bid

git diff shows you exactly what’s different between the live account and your .bid files. The output of refresh is the same canonical form fmt produces, so the diff is meaningful and minimal.

Reconcile mode (--in-place)

When you already maintain .bid files and somebody changes the account in the Google Ads UI — pauses a campaign, bumps a budget, renames an ad group — reconcile mode pulls just those changes back into your files:

Terminal window
bidsmith refresh --in-place ads/ # update ads/*.bid from live
bidsmith refresh --in-place --check ads/ # preview only, write nothing

It matches each live resource to the resource in your files that carries its bidsmith label, then updates only the scalar fields that drifted — a status, a name, a budget amount_micros, a bid. Everything else is left exactly as you wrote it: comments, blank lines, block order, and any resource bidsmith doesn’t manage.

The one exception is a campaign’s frequency_caps: because Google Ads treats the caps as a single setting, reconcile rewrites the whole set of blocks to match live rather than patching one number inside them.

~ campaigns.google_ads_campaign.summer_search (name, status)
~ campaigns.google_ads_campaign_budget.summer (amount_micros)
Updated 2 resources, 3 fields from live.

What reconcile doesn’t touch, by design:

  • New attributes. If a field drifted but isn’t written in your file at all (you were relying on the default), reconcile reports it rather than guessing where to insert it. Add it by hand, or bootstrap a fresh copy to see the full picture.
  • Computed values. An attribute set from a var., a local., or a reference to another resource is reported, not overwritten — otherwise the live value would replace the indirection you wrote on purpose. Change it at the source instead.
  • Structural changes — rewritten ad copy, added or removed keywords, changed targeting. Those aren’t a single value to patch; bidsmith plan shows them and apply is how you reconcile them.

Reconcile re-checks the whole project after editing and refuses to write anything if an edit would make a file invalid — so a surprising live value can never leave your .bid files broken.

Projects that use modules

Reconcile reads your tree exactly the way validate and plan do, so a template under templates/ that you instantiate with module blocks works normally — its variables come from the module block that calls it, not from the command line. (Root-level variables still take --var, same as plan.)

One template can stand behind many campaigns, though, and there’s only one place to write. So reconcile edits a template only when every instance drifted to the same new value:

~ google_ads_campaign.remarketing in templates/remarketing.bid (4 module instances) (status)
Updated 1 resource, 1 field from live.

If only some instances drifted, or they drifted to different values, reconcile reports it and leaves the template alone — a one-off change belongs in that instance’s inputs, not in the shared template.

Compact, folded output

refresh doesn’t just dump one resource per live object — it recognizes repeated structure and emits the same compact constructs a careful human would write by hand:

  • The same ad running in several ad groups becomes one ad_template, attached by reference. Ads that share a creative but point at different landing pages collapse onto one URL-agnostic template with per-ad final_urls / path1 / path2 overrides.
  • A headline or description list reused across several ads or templates is lifted into a locals block and referenced by name.
  • A negative-keyword list shared by several campaigns is lifted into a single local, referenced from each campaign’s negative_keywords block.

This matters because refresh is repeatable: because the folded form expands to exactly the same thing the verbose form does, a second refresh produces the same compact files — it never re-explodes a tree you (or a previous refresh) already folded. The folded files plan against your live account with zero changes, same as the long-hand version.

What gets pulled

Every resource type bidsmith currently understands (see the Resource reference for the full list). Internally, refresh uses the same SearchStream queries plan does — so anything plan sees as live state, refresh can capture.

What doesn’t get pulled

  • Performance data — bidsmith manages configuration only.
  • Resources outside the supported schema — types not yet modeled in src/schema.rs are silently ignored. The roadmap tracks resource-type coverage.

See also