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.bidfiles, overwriting its output. This is how you start a project from an existing account. - Reconcile (
--in-place) updates.bidfiles 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
bidsmith refresh [--output FILE | --dir DIR] [--include-removed] [--verbose]bidsmith refresh --in-place [PATH] [--check] [--var NAME=VALUE] [--verbose]Flags
| Flag | Description |
|---|---|
-o, --output FILE | Bootstrap: write everything to a single .bid file. Mutually exclusive with --dir. |
-d, --dir DIR | Bootstrap: split the output into <DIR>/account.bid and <DIR>/campaigns.bid. Mutually exclusive with --output. |
--in-place | Reconcile: update the existing .bid files at PATH (default .) in place instead of writing fresh output. Mutually exclusive with -o / -d. |
--check | With --in-place: print what would change and write nothing. |
--var NAME=VALUE | With --in-place: set a variable value. Repeatable. Same as plan. |
--include-removed | Include resources whose status is REMOVED. Default: drop them. (Bootstrap only.) |
--verbose | Print 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
| Code | Meaning |
|---|---|
0 | Successful refresh. |
1 | Authentication failure, API error, file write error, or other. |
Examples
Print the account to stdout
bidsmith refreshDumps 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
bidsmith refresh -o reality.bidSingle file with everything. Works well for small accounts.
Split into account- and campaign-scoped files
bidsmith refresh -d ads-bid/Creates two files:
ads-bid/account.bid— theproviderblock, 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
bidsmith refresh -o reality.bidgit diff reality.bid summer-2026.bidgit 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:
bidsmith refresh --in-place ads/ # update ads/*.bid from livebidsmith refresh --in-place --check ads/ # preview only, write nothingIt 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., alocal., 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 planshows them andapplyis 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-adfinal_urls/path1/path2overrides. - A headline or description list reused across several ads or
templates is lifted into a
localsblock and referenced by name. - A negative-keyword list shared by several campaigns is lifted into a
single
local, referenced from each campaign’snegative_keywordsblock.
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.rsare silently ignored. The roadmap tracks resource-type coverage.
See also
bidsmith pull— same data, raw API JSON instead of.bidformat.- Drift — what to do after
refreshshows differences. - Your first 10 minutes — refresh in the onboarding context.