Skill
Skill lroolle/ihme-cli/skill
Manage iCloud Hide My Email addresses — list, create, edit, deactivate, exportFrom its SKILL.md
npx -y skills add lroolle/ihme-cli --skill skillAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
5 things to look at
- skips confirmationTells the agent to proceed without asking first, 2 times: "Reserve the best immediately — don't ask unless no single candidate passes taste" and 1 more.
- reads credentialsReads from 3 credential sources: `IHME_SESSION_PATH` and 2 more.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 8 commands, including `make install` and 7 more.
- fetches URLsInstructs the agent to fetch 3 URLs, including https://github.com/lroolle/ihme-cli/releases/latest/download/ihme_macOS_arm64.tar.gz and 2 more.
SKILL.md
12.5 KB, ~3.2k tokens by cl100k_base, as published. Nobody here has run it
ihme — iCloud Hide My Email CLI
Setup
Prefer the local checkout when available, so agents use the newest CLI changes:
cd worktree/ihme-cli
make install
make install builds ihme and copies it to $GOPATH/bin/ihme, or to
~/go/bin/ihme when $GOPATH is unset. Make sure that directory is on PATH.
If the checkout is unavailable, install a release:
# macOS (Apple Silicon)
curl -sL https://github.com/lroolle/ihme-cli/releases/latest/download/ihme_macOS_arm64.tar.gz | tar xz && sudo mv ihme /usr/local/bin/
# macOS (Intel)
curl -sL https://github.com/lroolle/ihme-cli/releases/latest/download/ihme_macOS_x86_64.tar.gz | tar xz && sudo mv ihme /usr/local/bin/
# Linux
curl -sL https://github.com/lroolle/ihme-cli/releases/latest/download/ihme_linux_x86_64.tar.gz | tar xz && sudo mv ihme /usr/local/bin/
# Or via Go
go install github.com/lroolle/ihme-cli/cmd/ihme@latest
First run requires ihme auth login (interactive — Apple ID + 2FA).
Session lookup uses IHME_SESSION_PATH when set; otherwise it reads
$XDG_CONFIG_HOME/ihme/session.json, falling back to ~/.config/ihme/session.json.
ihme auth status --json first reads the local session file, then checks whether
that session can currently access iCloud. It includes Apple's /validate payload
as rawResponse. Use ihme auth status --local --json only when you want the
local file/timestamp check without a network request.
--verbose only logs method, URL, status, and size.
Current /validate success responses are account-info payloads with dsInfo
and webservices; they may omit a success boolean.
JSON response shapes
list --json → {"addresses":[{anonymousId,label,hme,isActive,createTimestamp,note,...}],"count":N,"hints":{...}}
view --json → {"result":{anonymousId,label,hme,forwardToEmail,isActive,...},"hints":{...}}
new --json → {"candidates":["[email protected]",...],"label":"...","hint":"ihme new <label> --address <addr>"}
new -y --json → {anonymousId,label,hme,isActive,...}
forward --json → {"forwardTo":"...","available":[...],"hint":"ihme forward set <email>"}
auth status → {"loggedIn":true,"appleId":"...","expired":false,"canAccessICloud":true,"rawResponse":{...},...}
deactivate → {"status":"deactivated","hme":"...","id":"...","hints":{...}}
reactivate → {"status":"reactivated","hme":"...","id":"...","hint":"..."}
Commands
# Auth check: local file + current iCloud access
ihme auth status --json
# Local auth file/timestamp only
ihme auth status --local --json
# List and search (hundreds of addresses supported)
ihme list --json --jq '.addresses[0:5]'
ihme list --search netflix --json
ihme list --active --tag dev --json
ihme list --sort label --json
# Create (two-step: generate candidates, then reserve)
ihme new github.com --json # step 1: get candidates
ihme new github.com --address [email protected] --json # step 2: reserve one
ihme new github.com --yes --json # one-shot: take first
# View and edit
ihme view github.com --json --jq '.result.hme'
ihme edit github.com --label GitHub --tag dev,work
# Lifecycle
ihme deactivate github.com --json
ihme reactivate github.com --json
ihme delete github.com --yes --json
# Export
ihme export --format json
ihme export --search github --active -o filtered.csv
# Forward-to
ihme forward --json
ihme forward set [email protected]
<ref> resolution
All commands accepting <ref> resolve in order: anonymousId (prefix >= 6 chars) > email > label (exact) > label (fuzzy).
Choosing an address
You'll see this address for years — in password managers, email threads, account settings. It's a mask, but it's still yours. The core test:
Does it make a picture, and is the picture one you'd keep?
Two checks, in order:
-
Can you see it? Concrete nouns with physicality beat abstractions.
hilltop_desertis a landscape.pollen_pipeis an object.63.fryer.immuneis a serial number. Specific things are memorable; categories are forgettable. -
Would you keep it? No deficit words (debts, gristle, paupers), no clinical tone (immune, generic, baseline), nothing that carries weight. An address is a micro-identity — it shouldn't feel assigned.
Bonus (elevates good to great, not a gate):
- Contextual resonance: does the address echo something about the service —
a brand name, a logo shape, a developer handle?
oranges.lobbyfor a service whose developer is@oran_geand whose logo is an O isn't luck — it's fit. Most addresses won't have this. When it's there, it's decisive.
Secondary signals (tiebreakers, not filters):
- Euphony: read it aloud. Pleasant vowel/consonant rhythm and natural stress help recognition in a list of 300+.
- No leading digits:
65.amperereads like a form field. Letters first. - Separator style: a distant tiebreaker. Never override a better image for a
preferred separator.
hilltop-desertbeatsrelay_stropregardless of format.
The best HME addresses feel like they could be a place on a map, a cocktail name, or an album title — evocative without trying.
Error handling
Errors include the fix command:
Error: <ref> required — an address label, email, or ID
Usage: ihme deactivate <ref>
Example: ihme deactivate github.com
Exit codes
- 0: success
- 1: error
- 2: not authenticated (run
ihme auth login)
Operational guide (for agents)
Creating an address
-
Derive the label and search key. For a URL, use the registrable domain without public suffix as the canonical label/search key:
https://atypica.ai/...becomesatypica;https://linear.app/...becomeslinear. Drop paths, query strings, callback URLs, referral parameters, dates, and campaign text. Keep the full URL only as context for the user or note. -
Check auth. Confirm the stored session can access iCloud before generating candidates:
ihme auth status --jsonIf it exits 2 or returns
canAccessICloud:false, the user must runihme auth logininteractively. -
Check first. Search for existing addresses before creating:
ihme list --search <search-key> --json--searchmatches label, address, and note by substring, so search the canonical key, then inspect returned labels for the intended service. Interpret matches by label, not by search key:- An active address with the SAME canonical label is a duplicate: ask
before creating another (embedded interactive runs:
ask_user). When you cannot ask, an explicitnew <label>request has already decided creation — proceed, and flag the existing duplicate prominently in the summary. - Addresses for the same service under DIFFERENT labels (older accounts, dated labels, per-team variants) are context, never a blocker: mention them in the note or summary and continue.
- An active address with the SAME canonical label is a duplicate: ask
before creating another (embedded interactive runs:
-
Generate and evaluate. Get candidates and apply the taste test above:
ihme new <label> --jsonEvaluate each candidate individually — don't let bad neighbors taint a good one. A pool with two duds and one strong image is not a "weak pool." Reserve the best immediately — don't ask unless no single candidate passes taste ("does it make a picture you'd keep?"). When NO candidate passes after rotation: interactively (embedded:
ask_user), offer your top two with a one-line image each and let the user pick; non-interactively, reserve the least-bad and say plainly it was a compromise. Embedded runs must articulate the verdict:reserve_addressrequiresrationale(the winner's image and why it fits) plus onerejectedentry per candidate you passed on, each naming its failure — the user judges your pick against these on the consent card. -
Reserve with a useful note.
ihme newsupports--note; Apple stores it in the address metadata, andihme list --searchsearches it. Keep notes compact and durable: why the address exists, the full signup/origin URL when useful, account/workspace context, referrer/invite code, or owner/team. Do not put passwords, recovery codes, API keys, cookies, or other secrets in notes.ihme new <label> --address <candidate> --note "signup: https://example.com/auth/signup?via=team; workspace: acme" --json -
Refresh the pool if it is weak. Apple's generate returns a FIXED pending pool that repeats — calling generate again returns the SAME candidates until a slot is consumed. So if no candidate passes taste and the pool stops changing, do not keep generating. Consume a slot to force a fresh pool: reserve a throwaway and immediately delete it, then generate again.
- Embedded agent:
refresh_candidatesdoes the whole maneuver in one call (reserve + delete + regenerate), capped at 2 per task. - Shell: reserve any candidate, delete it, then generate again.
ihme new <label> --address <throwaway> --json # consume a slot ihme delete <throwaway-id> --yes --json # clean it up ihme new <label> --json # fresh pool - If the refreshed pool still has no keeper, stop churning: take the least-bad and say plainly it was a compromise. Never ask the user to restart the session — you get a fresh budget next request.
- Embedded agent:
-
Show the result. State what was reserved and one line on why it was picked. If a compromise was made (weak pool, no good images), say so.
Labels
Use the service or team name as a bare noun. Dates age; names don't.
- Good:
github,linear,colaos,atypica - Avoid:
240501_chatgpt openai,0315 claude felix 2, full signup URLs, referral/callback parameters
Tags
Apply from a small controlled set when the user specifies context.
Common tags: #work, #dev, #personal, #throwaway, #team-<name>.
Hygiene
ihme list --sort date:asc to surface old addresses for audit.
Suggest pruning dead services quarterly.
Memory
You keep a memory across runs — a plain markdown graph (journals for what you did, pages per topic, a flashcards page loaded into every run). Use it for continuity:
- Recall before creating. Search memory for the service first;
you may have reserved for it before, and the past note carries the
account context. Shell:
ihme memory search <service>. Embedded:recall_memory. - Reservations journal themselves. Every reserve is written to memory automatically, linked to its service page. Never hand-record a reservation.
- Remember durable learnings, sparingly. When you learn a lasting
preference or a fact about a service worth carrying forward, save
one note. Pin it to the
flashcardstopic to have it loaded into every future run; use any other topic for on-demand recall. Never store secrets. Shell:ihme memory card <note>. Embedded:remember.
Execution adapters
The procedure and taste rules above are shared by two executors; only the operation mapping differs.
External agent (Claude Code etc.): run the shell commands as written above.
Embedded agent (ihme new <label> --agent for scoped creation,
ihme agent for the general interactive assistant): the same file is
embedded in the binary and invoked with the user's task. There is no
shell — operations map to in-process tools:
| Shell command | Embedded tool |
|---|---|
ihme auth status --json | auth_status |
ihme list --search <key> --json | search_addresses |
ihme new <label> --json (candidates) | generate_candidates |
| reserve + delete a throwaway, then generate | refresh_candidates |
ihme new <label> --address <a> --note <n> --json | reserve_address |
ihme deactivate <ref> --json | deactivate_address |
ihme edit <ref> ... | edit_note |
ihme memory search <query> | recall_memory |
ihme memory card <note> (or editing a page) | remember |
Embedded runs enforce the rotation cap (3 generation rounds) and
call budgets in code, and gate mutating actions outside the run's
granted scope behind user consent (--grant ask, the default) or
allow them unattended (--grant auto). Interactive embedded runs
also expose ask_user — one short question, answered on the
terminal, max 3 per run. Non-interactive runs must decide within
the task scope and record assumptions instead of stalling.
What ships with it: 2 files
1.2 KB alongside SKILL.md
- skill.go756 B
- skill_test.go433 B