8000 GitHub - xeb/myq: Zero-dependency Python 3 CLI for Chamberlain/LiftMaster myQ smart garage door openers (OAuth 2.0 + PKCE + Email MFA) · GitHub
[go: up one dir, main page]

Skip to content
xebPublic

About

Zero-dependency Python 3 CLI for Chamberlain/LiftMaster myQ smart garage door openers (OAuth 2.0 + PKCE + Email MFA)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

myq

Zero-dependency Python 3 CLI for checking the status of, opening, and closing Chamberlain / LiftMaster myQ smart garage door openers via the myQ v6/v5 REST API—including full support for myQ's OAuth 2.0 + PKCE + Email MFA login flow.

Features

  • Zero third-party dependencies: Uses only the Python 3.10+ standard library.
  • Unified ~/.config/myq/ State & Config: Stores both user configuration (~/.config/myq/config.json) and cached OAuth tokens (~/.config/myq/tokens.json, 0600) in ~/.config/myq/, keeping all personal setup, credentials, and tokens completely outside the repository.
  • Rolling OAuth Token Refresh: Automatically refreshes expired 12-hour access tokens via grant_type=refresh_token—so Email MFA is only needed on initial login.
  • Pluggable Credential & MFA Hooks: Fetch your myQ password and 6-digit Email MFA code on demand from any secret manager (pass, 1Password op, Bitwarden bw, macOS Keychain, systemd-creds), custom mail script (otp_cmd), environment variables, or interactive terminal prompt.
  • Live Door State Tracking: Checks current door state (OPEN, CLOSED, OPENING, CLOSING, STOPPED), avoids redundant commands when already in the requested state, and polls live state transitions until completion.

Assumptions & Requirements

  • Runtime: Python 3.10+ on Linux or macOS (no external pip packages required).
  • Account Type: Requires a standard Chamberlain / LiftMaster / Craftsman myQ account (partner-identity.myq-cloud.com) using email + password authentication (third-party federated logins such as "Sign in with Google/Apple" are not supported).
  • Supported Devices: Targets myQ garage door openers (device_family == "garagedoor" or devices reporting state.door_state). If your account has multiple garage doors, myq targets the first door by default unless you pass a door name substring or serial number on the command line.
  • Email MFA: On initial authentication (when ~/.config/myq/tokens.json does not yet exist or ./myq login is run), myQ sends a 6-digit verification code to the account's email address. By default, myq prompts interactively for this code in the terminal. For unattended/headless setups, either run ./myq login once interactively to seed ~/.config/myq/tokens.json (which then self-refreshes via refresh_token) or configure "otp_cmd" in ~/.config/myq/config.json.
  • Config & Token Location: Defaults to ~/.config/myq/ (or $XDG_CONFIG_HOME/myq/), overridable via $MYQ_CONFIG and $MYQ_TOKENS_FILE.

Quick Start

# Check garage door status (default command)
./myq
./myq status
./myq status --json

# Open the garage door (checks state, sends OPEN, and polls until OPEN)
./myq open

# Close the garage door (checks state, sends CLOSE, and polls until CLOSED)
./myq close

# Send open/close without waiting for transition completion
./myq open --no-wait
./myq close --no-wait

# Force a fresh OAuth + MFA login
./myq login

If you have multiple garage doors on your account, pass a door name substring or serial number as the second argument:

./myq open "Main Garage"
./myq close CG08XXXXXXXX

Configuring Credentials & MFA Hooks (~/.config/myq/)

myq never requires storing plaintext passwords in the repository or passing them on the command line. By default, it reads ~/.config/myq/config.json (overridable via $MYQ_CONFIG) and caches OAuth tokens in ~/.config/myq/tokens.json (0600, overridable via $MYQ_TOKENS_FILE). If no config file is present and myq is run in an interactive terminal, it prompts for your email, password, and the 6-digit emailed verification code.

Create ~/.config/myq/config.json (chmod 700 ~/.config/myq && chmod 600 ~/.config/myq/config.json) with your email and any password_cmd (shell string or argv array) that prints your myQ password to stdout:

Password Hook Examples (~/.config/myq/config.json)

1Password CLI (op):

{
  "email": "you@example.com",
  "password_cmd": ["op", "read", "op://Private/myQ/password"]
}

Unix pass:

{
  "email": "you@example.com",
  "password_cmd": ["pass", "show", "home/myq"]
}

Bitwarden CLI (bw):

{
  "email": "you@example.com",
  "password_cmd": ["bw", "get", "password", "myq"]
}

macOS Keychain (security):

{
  "email": "you@example.com",
  "password_cmd": ["security", "find-generic-password", "-a", "you@example.com", "-s", "myq", "-w"]
}

Linux systemd-creds (TPM2-sealed credential):

{
  "email": "you@example.com",
  "password_cmd": [
    "sudo",
    "systemd-creds",
    "decrypt",
    "--name=myq-password.cred",
    "/path/to/myq-password.cred",
    "-"
  ]
}

Automating Email MFA (otp_cmd / otp_prepare_cmd)

On initial login (when no valid refresh_token is cached in ~/.config/myq/tokens.json), myQ emails a 6-digit myQ Verification Code. By default, myq prompts for this code interactively in the terminal.

To automate MFA completely, place a helper script in ~/.config/myq/ and configure "otp_cmd" in ~/.config/myq/config.json (or $MYQ_OTP_CMD / --otp-cmd) with any command that prints the 6-digit code to stdout:

  • Before submitting the login form, myq records the Unix timestamp in $MYQ_OTP_SINCE and optionally runs "otp_prepare_cmd" (if configured), passing its stdout in $MYQ_OTP_STATE to "otp_cmd".
  • Once /AccountMfa/VerifyOtp is reached, myq executes "otp_cmd" and extracts the 6-digit code from stdout.

Environment Variables & CLI Flags

Setting Config Key (~/.config/myq/config.json) Environment Variable CLI Flag
Account Email "email" or "email_cmd" MYQ_EMAIL / MYQ_EMAIL_CMD --email
Password Hook "password_cmd" MYQ_PASSWORD_CMD --password-cmd
Password File "password_file" MYQ_PASSWORD_FILE --password-file
Password Value — MYQ_PASSWORD (interactive prompt if omitted)
OTP Prepare Hook "otp_prepare_cmd" MYQ_OTP_PREPARE_CMD —
OTP Fetch Hook "otp_cmd" MYQ_OTP_CMD --otp-cmd
Manual OTP Prompt — — --manual-otp
Token Cache Path — MYQ_TOKENS_FILE (defaults to ~/.config/myq/tokens.json)

When run under a systemd service with LoadCredentialEncrypted=myq-password.cred:..., myq automatically reads $CREDENTIALS_DIRECTORY/myq-password.cred.

Protocol Notes (How It Works)

  1. Direct Login Entry (/Account/Login): Cloudflare enforces a Managed Challenge (HTTP 429 cf-mitigated: challenge) on GET https://partner-identity.myq-cloud.com/connect/authorize. Because /connect/authorize only redirects unauthenticated clients to /Account/Login?ReturnUrl=/connect/authorize/callback?..., myq.py navigates directly to /Account/Login?ReturnUrl=... (with %20 URI encoding), receiving all required session and anti-forgery cookies (__cf_bm, myqidstid, AntiForgery.MyQ.Identity) with HTTP 200.
  2. Email MFA (/AccountMfa/VerifyOtp): After posting credentials to /Account/LoginWithEmail, IdentityServer redirects to /AccountMfa/VerifyOtp and emails a 6-digit security code, which myq.py retrieves via otp_cmd (or interactive prompt) and submits.
  3. Token Exchange (/connect/token): Exchanging the single-use com.myqops://android?code=... authorization code at POST https://partner-identity.myq-cloud.com/connect/token requires a firebase-appcheck-token JWT header with claims matching project 628160337454 (myq-production) to pass the edge gateway's 401.122 check. Subsequent token refreshes (grant_type=refresh_token) do not require App Check and issue rolling 12-hour tokens.

About

Zero-dependency Python 3 CLI for Chamberlain/LiftMaster myQ smart garage door openers (OAuth 2.0 + PKCE + Email MFA)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0