Skill
Skill lroolle/ihme-cli/skill
CLI for iCloud Hide My Email — for humans and AI agents
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.
One thing to look at
- 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.
What its author says it does
Copied from the file, not written here
Manage iCloud Hide My Email addresses — list, create, edit, deactivate, export
SKILL.md
12.5 KB, 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.