Skip to content

fdsouvenir/gmcli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gmcli

A standalone Go CLI that connects to Google Messages, archives conversations into a local SQLite + FTS5 database, and exposes a query surface suitable for shell use and LLM tool integrations.

Status: beta. Pairing, session persistence, sync loop, query CLI (messages, contacts, chats), best-effort history backfill, send commands, media download, and an LLM skill (skills/google-messages) are wired up and covered by the automated test suite. Live-device behavior still depends on the unofficial Google Messages web protocol, so validate auth, sync, history, media, and send flows on your own account before relying on unattended operation. See docs/research/phase-1-libgmessages.md for the design notes that motivated this layout, and skills/README.md for the skill installation guide.

What it is

  • Standalone. No Matrix server, no Docker, no bridge daemon. Just a Go binary, a SQLite file, and a phone running Google Messages.
  • Read-first. Phone-mutating operations (sending texts and reactions) are gated behind explicit flags. The default is to observe, not to send.
  • Local. Messages live in a single SQLite database under your data directory (XDG-compliant). Nothing is uploaded anywhere.
  • AGPL-3.0. gmcli imports pkg/libgm from mautrix/gmessages, which is licensed AGPL-3.0. That makes gmcli a derivative work and obligates the same license for the whole program. See LICENSE and NOTICE.

How it works

pkg/libgm reverse-engineers the Google Messages web client protocol. After a one-time QR pairing handshake, it maintains an authenticated session with your paired phone — all messages flow through the phone, which proxies them to Google's relay infrastructure. gmcli wraps that session with an event loop that writes incoming messages, conversation updates, and contact data to a local SQLite database, and exposes the database through a CLI.

The phone must be online and have Google Messages installed for the relay to work. Pairing tokens are refreshed automatically; full re-pairing is required roughly every 14 days of inactivity (Google's policy, not ours).

Install

Requires Go 1.24 or newer.

git clone https://github.com/fdsouvenir/gmcli
cd gmcli
go build -o gmcli .

For a source build whose gmcli version output includes the current tag or commit, inject it at link time:

go build -ldflags "-X github.com/fdsouvenir/gmcli/cmd.Version=$(git describe --tags --always --dirty)" -o gmcli .

Pre-built binary distribution and Homebrew packaging are planned after the initial beta releases.

Current limits

  • Live-device coverage is still limited. Before relying on gmcli unattended, test auth, sync, query commands, history backfill, media download, and a deliberate send with your own Google Messages account.
  • History backfill is best-effort and depends on what Google Messages returns through the paired phone.
  • The phone must be online for sync, backfill, sends, and media downloads.
  • The SQLite database is local but unencrypted. Use filesystem encryption if you need at-rest protection.
  • The protocol depends on the unofficial libgm reverse-engineered Google Messages web protocol and can break if Google changes that protocol.

Quick start

# 1. One-time pairing (renders a QR code in the terminal — scan with the
#    Google Messages app on your phone, Settings → Device pairing → QR code).
gmcli auth

# 2. Sync messages from the phone into the local database. --follow keeps
#    the connection open and writes new messages as they arrive.
gmcli sync --follow

# 3. Query the local archive (read-only).
gmcli chats list                              # most-recent conversations
gmcli chats show <conversation-id>            # header + recent messages
gmcli messages search "dinner"                # FTS5 across all conversations
gmcli messages list --conv <conv-id>          # message list with filters
gmcli messages show <message-id>              # single message detail
gmcli messages context <message-id>           # surrounding messages
gmcli contacts search alice                   # name/number/alias substring match
gmcli contacts show <participant-id-or-num>   # contact detail

# 4. Local-only labels.
gmcli contacts alias set --id <pid> --alias "Mom"
gmcli contacts alias list                     # list all set aliases
gmcli contacts alias rm --id <pid>

# 5. Best-effort history backfill, modeled after wacli.
gmcli history backfill --chat <conv-id> --requests 10 --count 50
# JSON output reports protocol records separately from the chat message delta:
# fetched_messages, sync_records_processed, messages_before, messages_after,
# messages_added_for_chat.

# 6. Write to the phone (always requires --read-only=false).
gmcli --read-only=false send text --to <conv-id> --message "on my way"
gmcli --read-only=false send react --message <msg-id> --emoji "👍"
gmcli media download --message <msg-id>
# `send text` only reports success after Google Messages echoes the outgoing
# message back with its canonical message_id.

# Every command supports --json for machine-readable output and --full to
# disable truncation in tables.
gmcli --json chats list | jq '.[0].name'

Global flags

Flag Default Purpose
--store DIR $XDG_STATE_HOME/gmcli Where session, SQLite, and downloaded media live.
--read-only true Block commands that send texts or reactions through the phone.
--json false Emit machine-readable output.
--full false Disable truncation in tabular output.
--log-level info Verbosity (trace/debug/info/warn).

Layout

cmd/                  Cobra command tree (auth, sync, version, doctor,
                      messages, contacts, chats, send, media)
internal/
  gm/                 libgm wrapper — pairing, session, events, send/react,
                      WaitForReady, DownloadMedia
  store/              SQLite + FTS5 store (schema v2: + aliases table)
  sync/               Event-to-store pump
  output/             Shared JSON / tab-aligned table renderers
  paths/              XDG path resolution (XDG_STATE_HOME)
  logging/            zerolog setup
skills/
  google-messages/    LLM skill bundle - archive playbook for assistants
docs/research/        Phase 1 research notes

LLM integration

The bundled OpenClaw skill lives in skills/google-messages. It is published on ClawHub as Google Messages Local Archive (google-messages-local-archive) for searching, summarizing, and answering questions from a local Google Messages SMS/RCS archive with read-only commands by default.

Privacy

  • All data is local. gmcli does not phone home.
  • Session tokens are stored in $XDG_STATE_HOME/gmcli/session.json with mode 0600.
  • Media attachments are referenced by ID in the database; bytes are not downloaded by default. Use gmcli media download --message <message-id> for explicit downloads.
  • The SQLite file is unencrypted. If you need at-rest encryption, layer your own filesystem encryption (FileVault, LUKS, etc.).

Attribution

  • libgm — the Google Messages protocol library this CLI depends on — was written by Tulir Asokan and the mautrix contributors. License: AGPL-3.0. gmcli would not be possible without their reverse-engineering work.
  • The CLI verb structure is inspired by Peter Steinberger's wacli for WhatsApp.
  • Storage and MCP-tool patterns draw from openmessage by Max Ghenis, released under the Unlicense.

License

GNU Affero General Public License, version 3 or later. See LICENSE for the full text and NOTICE for the third-party notices required by upstream licenses.

About

Google Messages CLI

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages