apple-contacts
Read, search, create, update, or delete Apple Contacts (Contacts.app / iCloud address book) from the shell on macOS, including bulk exports and importing…
Skill by alexjmiller5
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/alexjmiller5-apple-contacts
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: productivity
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/apple-contacts
What's inside
- Skill name
apple-contacts- Description
- Read, search, create, update, or delete Apple Contacts (Contacts.app / iCloud address book) from the shell on macOS, including bulk exports and importing contacts into the Notion People DB. Use for any task touching the user's contacts, phone numbers, the address book, or 'who is X' lookups.
- License
- MIT
- Instructions
- 170 lines in SKILL.md · view on GitHub
Files (2)
- SKILL.md
- sqlite.md · references/
SKILL.md (first lines)
# Apple Contacts
Zero-install: two macOS built-ins cover everything, no third-party CLI.
| Path | Use for | Speed |
|------|---------|-------|
| `sqlite3` read of the AddressBook DB | bulk reads, exports, joins, JSON output | ~10 ms for ~1000 contacts |
| `osascript` (AppleScript → Contacts.app) | targeted lookups, ALL writes, vCards | ~1 s per call; looping all contacts takes ~1 min |
| pyobjc + Contacts framework (CNContacts) | bulk WRITES, or shielding from schema churn | ~0.9 s for ~1000 contacts |
**NEVER write to the SQLite DB** - it is Contacts.app's and iCloud sync's
private store; reads are safe (`mode=ro`), writes corrupt sync. All mutations
go through AppleScript.
## Permissions (TCC)
- AppleScript needs an Automation grant (calling app → Contacts); sqlite3
needs Full Disk Access. Both must be granted on the invoking terminal.
- Error `-1743` or "unable to open database": System Settings → Privacy &
Security → Automation (or Full Disk Access) for the terminal app.
- TCC prompts don't fire in embedded terminals (VS Code); trigger the grant
once from Terminal.app.
## Bulk reads (sqlite3)
The root DB `~/Library/Application Support/AddressBook/AddressBook-v22.abcddb`
is nearly empty - real data lives in per-account DBs at
`Sources/<uuid>/AddressBook-v22.abcddb`. Query every source:
```bash
for db in ~/Library/Application\ Support/AddressBook/Sources/*/AddressBook-v22.abcddb; do
sqlite3 -json "file:$db?mode=ro" "
SELECT r.ZUNIQUEID AS id, r.ZFIRSTNAME AS first, r.ZLASTNAME AS last,
r.ZMIDDLENAME AS middle, r.ZNICKNAME AS nick,
r.ZORGANIZATION AS org, r.ZJOBTITLE AS title,
CASE WHEN strftime('%Y', r.ZBIRTHDAY + 978307200, 'unixepoch', 'localtime') < '1900'
THEN strftime('%m-%d', r.ZBIRTHDAY + 978307200, 'unixepoch', 'localtime')
ELSE date(r.ZBIRTHDAY + 978307200, 'unixepoch', 'localtime') END AS birthday,
(SELECT group_concat(ZFULLNUMBER, '; ') FROM ZABCDPHONENUMBER WHERE ZOWNER = r.Z_PK) AS phones,
(SELECT group_concat(ZADDRESS, '; ') FROM ZABCDEMAILADDRESS WHERE ZOWNER = r.Z_PK) AS emails
FROM ZABCDRECORD r
WHERE r.ZFIRSTNAME IS NOT NULL OR r.ZLASTNAME IS NOT NULL OR r.ZORGANIZATION IS NOT NULL;"
done
```
`ZUNIQUEID` is the same `UUID:ABPerson` id AppleScript uses - the stable
cross-path key. Full schema, more columns (socials, URLs, notes, addresses),
and label decoding: [references/sqlite.md](references/sqlite.md).
## Targeted lookups (AppleScript)
```bash
# Count / list names
osascript -e 'tell application "Contacts" to get name of every person whose name contains "John"'
# Full details for one person (NEVER `first person whose` - buggy; filter then item 1)
osascript -e 'tell application "Contacts"
set matches to every person whose name contains "John"
if (count of matches) > 0 then
set p to item 1 of matches
return {id of p, name of p, value of phones of p, value of emails of p, organization of p}
end if
end tell'
# By id (stable - prefer over names once known)
osascript -e 'tell application "Contacts" to get name of person id "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX:ABPerson"'
# Single-contact vCard
osascript -e 'tell application "Contacts" to get vcard of person id "...:ABPerson"'
```
Phone search (`whose value of phones contains "..."`) is exact-match on the
stored format (`+1XXXXXXXXXX` ≠ `XXXXXXXXXX`) - for phone/email lookups use
the sqlite path with `LIKE` instead. Name `contains` is case-insensitive
partial; `is` is exact. No match returns empty output, not an error.
## Writes (AppleScript)
Every mutation needs an explicit `save` inside the `tell` block or it
silently doesn't persist. All verified working:
```bash
# Create
osascript -e 'tell application "Contacts"
set p to make new person with properties {first name:"Jane", last name:"Doe", organization:"Acme"}
make new phone at end of phones of p with properties {label:"mobile", value:"+15551234567"}
make new email at end of emails of p with properties {label:"work", value:"jane@example.com"}
save
return id of p
end tell'
# Edit a property (birthday: build the date from components - literals are locale-fragile)
osascript -e 'tell application "Contacts"
set d to current date
set {year of d, month of d, day of d} to {1997, 4, 20}
set birth date of person id "...:ABPerson" to d
save
end tell'
# Delete
osascript -e 'tell application "Contacts"
delete person id "...:ABPerson"
save
end tell'
```
Labels: `mobile`, `home`, `work`, `main`, `other` (or custom strings).
Confirm with the user before deleting or bulk-editing real contacts.
## Gotchas
- Bulk `get vcard of every person` fails (error `-1741`, reply too large);
per-person looping works but is slow. Bulk = sqlite.
- Long AppleScript ops need `with timeout of N seconds ... end timeout` (the
default Apple-event timeout is 2 min, and osascript otherwise hangs).
- Birthday with no year is stored as year **1604** (Apple's no-year
sentinel) - test `year < 1900` and emit MM-DD. (`ZBIRTHDAYYEARLESS` is not
a flag: it's the MM-DD as a timestamp in year 2001, set for every birthday.)
- Raw labels in sqlite/vCards look like `_$!<Mobile>!$_` - strip to the innerFrom alexjmiller5/agent-config-public, MIT.
More from alexjmiller5/agent-config-public
- 0.570score
language-selection
alexjmiller5
Use when choosing a programming language or app stack, comparing Go, Rust, Zig or other languages, starting a new app whose stack is undecided, or proposing a…
SkillAFreshness: AClaude Code +9 - 0.570score
bug-hunt
alexjmiller5
Use when asked to bug-hunt, dogfood, exploratory-test, or check a website for broken interactions and responsive UI problems, especially without an existing…
SkillAFreshness: AClaude Code +9 - 0.570score
forge-skill
alexjmiller5
Use when creating, rewriting or improving an agent skill (a SKILL.md) - "make a skill for X", "turn this workflow into a skill", "improve this skill", "this…
SkillAFreshness: AClaude Code +9 - 0.570score
groupme
alexjmiller5
Use when a task touches GroupMe in any way - searching or reading group chats or DMs for historical reference ("what did the group chat say about X", "find…
SkillAFreshness: AClaude Code +9 - 0.566score
cherri
alexjmiller5
The Cherri programming language - write, compile, and debug iOS Shortcuts as code (.cherri files).
SkillAFreshness: AClaude Code +9 - 0.565score
coordinator
alexjmiller5
Use when an agent is dispatched as the coordinator of a batch of tasks - a high-capability model that reads, designs, decides and reviews, and hands…
SkillAFreshness: AClaude Code +9 - 0.565score
afk
alexjmiller5
Use when the user is leaving and wants work to continue without them - "I have to leave", "I'll be back in a few hours", "do as much as you can before you…
SkillAFreshness: AClaude Code +9 - 0.565score
herdr-crew
alexjmiller5
Use when one agent should coordinate other coding agents in Herdr tabs - dispatching a batch of tasks to parallel agents the user can watch, monitoring them…
SkillAFreshness: AClaude Code +9 - 0.565score
icons
alexjmiller5
the user's icon standard - which set to use for every icon job (mono UI, colorful/object, brand logos), all delivered via Iconify URLs, plus the one design…
SkillAFreshness: AClaude Code +9 - 0.565score
discounts
alexjmiller5
Use when the user is about to buy something and wants it cheaper - "find a discount", "promo code for X", "any deals on this", "can I get this cheaper"…
SkillAFreshness: AClaude Code +9 - 0.565score
mac-control
alexjmiller5
See and drive a Mac's screen from a shell - screenshots, accessibility tree, clicking, typing, key presses, dismissing dialogs - locally or on a…
SkillAFreshness: AClaude Code +9 - 0.560score
chrome-control
alexjmiller5
Invoke FIRST for blocked web access (Reddit, Instagram, Wirecutter/NYT, HTTP 403, bot checks, login/paywall stubs) and ANY browser task - Chrome, pages, tabs…
SkillAFreshness: AClaude Code +9
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 13, 2026 (16 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from alexjmiller5
- 0.570score
bug-hunt
alexjmiller5
Use when asked to bug-hunt, dogfood, exploratory-test, or check a website for broken interactions and responsive UI problems, especially without an existing…
SkillAFreshness: AClaude Code +9 - 0.570score
language-selection
alexjmiller5
Use when choosing a programming language or app stack, comparing Go, Rust, Zig or other languages, starting a new app whose stack is undecided, or proposing a…
SkillAFreshness: AClaude Code +9 - 0.570score
groupme
alexjmiller5
Use when a task touches GroupMe in any way - searching or reading group chats or DMs for historical reference ("what did the group chat say about X", "find…
SkillAFreshness: AClaude Code +9 - 0.570score
forge-skill
alexjmiller5
Use when creating, rewriting or improving an agent skill (a SKILL.md) - "make a skill for X", "turn this workflow into a skill", "improve this skill", "this…
SkillAFreshness: AClaude Code +9 - 0.566score
cherri
alexjmiller5
The Cherri programming language - write, compile, and debug iOS Shortcuts as code (.cherri files).
SkillAFreshness: AClaude Code +9 - 0.565score
mac-control
alexjmiller5
See and drive a Mac's screen from a shell - screenshots, accessibility tree, clicking, typing, key presses, dismissing dialogs - locally or on a…
SkillAFreshness: AClaude Code +9
Cite this page
apple-contacts skill. Agent Mart. https://agentmart.dev/skills/alexjmiller5-apple-contacts (last updated 2026-10-24)