Skip to main content

🔑 apwcli

Apple Passwords (iCloud Keychain) from the terminal. Read passwords and one-time codes, save logins, script it all.

CI License: MIT Python 3.12+ macOS

Website · Commands · Python library · Examples · How it works


  • Passwords & one-time codes — read, save, and update Apple Passwords entries
  • Agent-ready — bundled Claude skill and MCP server (apwcli mcp install)
  • Safe by default — passwords are masked on screen; -c copies to the clipboard instead
  • Scriptable — JSON/TSV output everywhere; Python API via apwlib
  • Zero setup — a background daemon auto-starts on first use and pairs on demand

Install

brew install michel-tricot/tap/apwcli   # or: uv tool install apwcli, pipx install apwcli

Or from a clone: uv sync, then uv run apwcli --help.

Requires macOS with a supported browser installed (Chrome, Brave, Edge, or Chromium); the iCloud Passwords extension itself is downloaded automatically from the Chrome Web Store.

Quick start

apwcli pw get github.com                 # saved entries (passwords masked)
apwcli pw get github.com me@example.com  # narrow to one account
apwcli otp get github.com                # current one-time code

The first command sets everything up: it starts the daemon and, if needed, pairs — macOS shows a 6-digit PIN, apwcli prompts for it, and you're set for as long as the daemon runs.

Something not working? apwcli doctor checks the whole chain — browser, extension, daemon, pairing — and tells you what to fix.

Security

This is a tool for your passwords, so here's exactly what it does with them:

  • Nothing leaves your Mac. apwcli talks only to Apple's local iCloud Passwords helper, through the official extension running in a browser on your machine. There are no servers, telemetry, or network calls of our own.
  • Apple's crypto does the crypto. Pairing (SRP) and per-command encryption (AES-GCM) run inside the real extension; apwcli is transport around it and never implements or handles key material itself.
  • Secrets stay off your screen and out of scrollback. Tables mask passwords by default (--show to reveal); text/json output is unmasked for piping. -c copies to the clipboard instead of printing, and the clipboard is auto-cleared after 20s (--clear-after).
  • Agents never see plaintext passwords by default. The MCP server exposes one-time codes, saving, and pairing — but not password reads unless you explicitly run it with --allow-passwords (MCP results travel to the model provider).
  • Nothing sensitive is logged. The daemon log records lifecycle and errors only; command bodies are encrypted inside the browser and never written in plaintext.

Full details — the launch constraint, the pairing handshake, the threat model — are in the design notes. Found a vulnerability? See SECURITY.md.

Commands

Passwords

apwcli pw get github.com                      # entries for a site, passwords masked
apwcli pw get github.com me@example.com       # narrow to one account
apwcli pw get github.com me@example.com -c    # copy to clipboard, print nothing
apwcli pw get github.com me@example.com --show   # reveal in the table
apwcli pw save github.com me@example.com      # create/update (prompts)
printf '%s' "$PW" | apwcli pw save github.com me@example.com   # piped: no prompt
apwcli pw generate github.com me@example.com  # make a strong password and save it
apwcli pw generate github.com me@example.com -c   # …and copy it, don't print

Sites match by registrable domain: github.com, https://gist.github.com/x, and www.github.com all find the same accounts. Clipboard copies (-c) are wiped after 20 seconds; tune it with --clear-after (0 keeps them).

One-time codes

apwcli otp get github.com        # the current code
apwcli otp get github.com -c     # straight to the clipboard
apwcli otp list github.com       # accounts that have codes

Scripting

Data commands take --format / -o: table (default), json, or text (TSV for piping). Pipes always carry the real values — masking is only for tables on screen.

apwcli pw get github.com me@example.com -o text | cut -f3
apwcli otp get github.com -o json | jq -r '.results[0].code'

Errors exit with the protocol status code (9 = daemon down or not paired) and print error: … to stderr, or a JSON object with -o json.

Daemon & pairing

Commands auto-start a background daemon on first use and pair on demand — an unpaired command pops the macOS PIN dialog and prompts for the code, so you never launch or supervise anything. Without a terminal (scripts, agents, GUI apps), the prompt becomes a small on-screen PIN window instead. A pairing lasts for the daemon's lifetime; keeping the daemon running keeps the PIN rare.

apwcli doctor           # diagnose the whole setup (browser, extension, pairing)
apwcli daemon status    # daemon / extension / pairing state
apwcli daemon pair      # pair explicitly; --pin 123456 to skip the prompt
apwcli daemon restart   # replace a wedged daemon with a fresh one
apwcli daemon logs      # tail the daemon log (-f to follow, --clear to wipe)
apwcli daemon stop      # stop the daemon and its browser

Agents

apwcli ships with integrations for AI agents:

apwcli skills install          # install the Claude skill into ~/.claude/skills
apwcli mcp install             # wire the MCP server into Claude, Cursor, VS Code, …

The MCP server exposes one-time codes, saving, and pairing — never plaintext passwords unless you start it with apwcli mcp run --allow-passwords (MCP tool results travel to the model provider; see the design notes).

Library

apwlib is the Python API behind the CLI:

from apwlib import ApplePasswords

pw = ApplePasswords(pin_provider=lambda: input("PIN: "))
for entry in pw.get_password("github.com", "me@example.com"):
    login(entry.username, entry.password)  # typed entries; nothing printed

Full guide and API reference on the website; runnable scripts in examples/.

Contributing

Contributions are welcome. The repository is a uv workspace with two packages: apwcli (this project, src/apwcli) and apwlib. Set up a checkout:

git clone https://github.com/michel-tricot/apwcli
cd apwcli
uv sync

Before committing, run the full validation suite — format, lint, typecheck, tests — and keep it green; CI runs the same thing:

scripts/check.sh

Work on the documentation site (MkDocs Material):

uv sync --group docs
uv run mkdocs serve      # live preview at http://127.0.0.1:8000

Contributor and agent guidelines live in AGENTS.md; design notes in docs/design/apwlib.md.

License

MIT © Michel Tricot · Not affiliated with Apple. Apple Passwords and iCloud Keychain are trademarks of Apple Inc.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

apwcli-0.1.1.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

apwcli-0.1.1-py3-none-any.whl (21.0 kB view details)

Uploaded Python 3

File details

Details for the file apwcli-0.1.1.tar.gz.

File metadata

  • Download URL: apwcli-0.1.1.tar.gz
  • Upload date:
  • Size: 16.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for apwcli-0.1.1.tar.gz
Algorithm Hash digest
SHA256 0e7eaef77ded05f9722b165eef8b680b4155697642f209dc8a8be1f6dff21f38
MD5 679ae8195aaf61afdceb8e6a39e9035d
BLAKE2b-256 2737ee3c2844b96480ee6252b3ad5de4771ea2bc3c792de96ecdc11b3734d506

See more details on using hashes here.

File details

Details for the file apwcli-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: apwcli-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 21.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for apwcli-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7268008b26850c64f5016eb60a872786dc6b5ce6c70da6082cc0182845f0c337
MD5 2e9f39c8561adeb9b08ec955d856f844
BLAKE2b-256 b7014fe1d5575626bdb79b0ab61325180a8a5f02a6cb1dd358da8a3c102a3953

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page