Understanding the wacli Bootstrap Sync Process After Authentication
The bootstrap sync process in wacli is a post-authentication routine that imports contacts and groups, consumes the full WhatsApp history sync, stores live messages, and automatically exits after a configurable idle period.
When you authenticate with wacli auth, the tool immediately executes a bootstrap sync process that prepares your local SQLite database for WhatsApp operations. This routine, implemented in internal/app/sync.go and internal/app/bootstrap.go, ensures you have a complete local copy of your contacts, groups, and message history before the process terminates.
What Triggers the Bootstrap Sync Process?
The bootstrap sync activates in two scenarios:
- CLI authentication: Running
wacli authcreates anAppinstance and invokesSyncwithSyncModeBootstrap(seecmd/wacli/auth.go, lines 33-45) - Programmatic initialization: Calling
App.Sync(context.Background(), app.SyncOptions{Mode: app.SyncModeBootstrap, ...})directly
Unlike continuous sync modes, the bootstrap process imports all historical data and then exits after a period of inactivity, making it ideal for initial setup or one-time backups.
Step-by-Step Breakdown of the Bootstrap Sync
The Sync function in internal/app/sync.go orchestrates a 10-step sequence:
1. Initialize the WhatsApp Client
The process calls a.OpenWA() to ensure the whatsmeow client is ready, then a.Connect establishes the WebSocket connection. If no cached credentials exist, the system displays a QR code for authentication (controlled by the AllowQR option).
2. Start Optional Media Workers
If DownloadMedia is enabled in SyncOptions, the sync routine initializes a pool of background workers to fetch media files while message processing continues (see internal/app/sync.go, lines 57-64).
3. Import Contacts
The refreshContacts function in internal/app/bootstrap.go (lines 8-26) retrieves all contacts via wa.GetAllContacts, then persists each one to the SQLite database using db.UpsertContact. This runs by default during bootstrap (opts.RefreshContacts is true).
4. Import Groups
Similarly, refreshGroups in internal/app/bootstrap.go (lines 29-45) fetches joined groups via wa.GetJoinedGroups and stores them using db.UpsertGroup and db.UpsertChat. This ensures group metadata exists before historical messages arrive.
5. Consume History Sync Events
After connection, WhatsApp emits a *events.HistorySync containing all conversations and historic messages. The event handler in internal/app/sync.go (lines 15-40 of the handler) iterates through every message, constructs a ParsedMessage, and stores it via storeParsedMessage.
6. Process Live Messages
While the bootstrap connection remains active, new incoming messages are handled identically to historic ones. They are parsed, stored, and optionally queued for media download (see internal/app/sync.go, lines 94-114).
7. Idle Exit Mechanism
Bootstrap mode terminates automatically rather than running forever. A ticker monitors the timestamp of the last processed event; if the client remains idle for the duration specified by IdleExit (default 30 seconds), the process prints a notice and returns. This logic resides in internal/app/sync.go (lines 94-118).
8. Return Results
The Sync function concludes by returning a SyncResult struct containing the count of messages stored during the run (see internal/app/sync.go, lines 44-45).
Practical Usage Examples
Authenticate with Full Bootstrap Sync
Run the following to authenticate, import contacts and groups, download media, and exit after 30 seconds of inactivity:
wacli auth --download-media
Under the hood, this executes Sync with SyncModeBootstrap as implemented in cmd/wacli/auth.go (lines 33-45).
Configure Custom Idle Timeout
Extend the idle period to 2 minutes before automatic exit:
wacli auth --idle-exit=2m
This maps to SyncOptions.IdleExit in cmd/wacli/auth.go (lines 68-70) and is honored by the idle-exit logic in sync.go.
Programmatic Bootstrap in Go
Embed the bootstrap sync in your own application:
package main
import (
"context"
"time"
"github.com/steipete/wacli/internal/app"
)
func main() {
// Initialize App with configuration
a, _ := app.NewApp(/* config */)
// Execute bootstrap sync
res, err := a.Sync(context.Background(), app.SyncOptions{
Mode: app.SyncModeBootstrap,
AllowQR: true,
RefreshContacts: true,
RefreshGroups: true,
DownloadMedia: true,
IdleExit: 30 * time.Second,
})
if err != nil {
panic(err)
}
println("Messages stored:", res.MessagesStored)
}
This executes the full 10-step bootstrap sequence defined in internal/app/sync.go.
Key Source Files and Architecture
Understanding the bootstrap sync requires familiarity with these implementation files:
internal/app/sync.go– Core synchronization engine containing the mainSyncfunction, connection handling, event processing, and idle-exit timer (lines 94-118).internal/app/bootstrap.go– Helper functionsrefreshContacts(lines 8-26) andrefreshGroups(lines 29-45) that import address book data before history synchronization.cmd/wacli/auth.go– CLI entry point that parses--download-mediaand--idle-exitflags, then invokesSyncwithSyncModeBootstrap(lines 33-45, 68-70).internal/store/– SQLite persistence layer implementingUpsertContact,UpsertGroup, andUpsertMessageused throughout the bootstrap steps.internal/wa/– Thin wrapper aroundwhatsmeowprovidingGetAllContacts,GetJoinedGroups, andParseHistoryMessagefor the bootstrap import routines.
Summary
- The bootstrap sync process initializes your local WhatsApp database immediately after authentication via
wacli auth. - It executes a 10-step sequence: connection setup, media worker initialization, contact import, group import, history sync consumption, live message handling, and idle-exit termination.
- Key entry points are the CLI command
wacli authand the programmatic APIApp.SyncwithSyncModeBootstrap. - The process automatically terminates after a configurable idle period (default 30 seconds), unlike continuous sync modes.
- Implementation spans
internal/app/sync.go,internal/app/bootstrap.go, andcmd/wacli/auth.go.
Frequently Asked Questions
How long does the bootstrap sync process take to complete?
The duration depends on your WhatsApp account size. Importing contacts and groups completes in seconds, but history sync duration varies with message volume. The process automatically exits 30 seconds after the last activity by default, or you can configure this with the --idle-exit flag.
What is the difference between bootstrap sync and continuous sync?
Bootstrap sync (SyncModeBootstrap) imports all historical data and exits after an idle period, making it ideal for initial setup or one-time backups. Continuous sync maintains a persistent connection, processing live messages indefinitely without automatic termination.
Why are contacts and groups imported before the history sync?
The refreshContacts and refreshGroups functions in internal/app/bootstrap.go populate the database with metadata needed to properly associate historical messages with their senders and group contexts. This ensures that when HistorySync events arrive, the foreign key relationships in the SQLite database remain consistent.
Can I skip media download during bootstrap sync?
Yes. The --download-media flag is optional. When omitted, the bootstrap sync imports text messages, contacts, and groups without fetching media files. You can enable media download later by running wacli sync with the appropriate flags.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →