Guide
Work with your contact book
Start with the people you already know. There is no app to open. Your agent runs PeopleBlade's commands against a private database on your computer. Every command can print JSON with --json. Your contact book is a SQLite database on your computer. Data leaves it only when you run a command that sends something: device sync, cloud sync, a research check on public profiles, an exposure check against breach and public-record sources, or a Hunter work-email lookup. Each of those commands states what it sends.
Start without an account
Install the CLI on macOS or Linux with Bun 1.3.14 or newer, then create an empty contact book. These commands need no account, no password, and no import.
bun add --global @hraness/peopleblade@0.12.1
peopleblade --version
peopleblade init
peopleblade statsAdd --help to any command to see its options before you run it. Apple Contacts and iMessage need macOS. On Linux, start with a contact file or a LinkedIn export.
Teach your agent
Your agent learns the commands from the CLI itself: peopleblade --help lists the common ones, and peopleblade help advanced lists every command and flag. The package also carries the PeopleBlade Agent Skill, which tells your agent when to run each command.
peopleblade skill install # Claude Code and Codex
peopleblade skill install --agent agents # ~/.agents/skills
peopleblade skill install --dir PATH # any skills folderStart a new agent session so it loads the skill. Run the install again after you upgrade PeopleBlade; peopleblade skill path prints where the bundled copy lives.
Import what you already have
Your address books, official data exports, and message history already say a lot about who you know. Choose each source yourself; each contact in the book lists the imports it came from.
# On a Mac: Apple Contacts, then who you message and when
peopleblade contacts sync
peopleblade imessage sync
# Anywhere: an official LinkedIn export
peopleblade linkedin import /path/to/Complete_LinkedInDataExport.zip
peopleblade statsiMessage needs Full Disk Access for the app that runs PeopleBlade, such as your terminal. macOS never asks for it: turn it on in System Settings, Privacy & Security, Full Disk Access, then run the sync again.
LinkedIn connections come only from the official export. After that import, linkedin contact-info can read the Contact info panel of one connection through GhostGet; it never lists connections or reads messages.
Imports keep no message text and never search, research from, or upload it. Only who took part, when, and how often enters the book.
Connect signed-in accounts
Google Contacts, Gmail, Beeper, WhatsApp, and Substack come in through GhostGet, a separate Hraness tool that signs in to web accounts on your computer. You install it and sign in to each account yourself. PeopleBlade asks it for named read operations and checks each answer before saving anything, so your agent never holds a password or a signed-in browser. Signed-in accounts need GhostGet 0.18.44 or a later 0.18 release.
bun add --global https://github.com/hraness/ghostget/releases/download/v0.18.45/hraness-ghostget-0.18.45.tgz
ghostget adapter sync-bundled
ghostget browsers # prints the flags for each browser profile on this computerThen connect each account once and run its import. Each PeopleBlade command uses the account name shown here by default; pass --auth NAME to use another.
# Google Contacts and Gmail, with your own Google OAuth desktop client
ghostget auth login gmail-main --client-file /path/to/desktop-client.json
peopleblade google sync
peopleblade google interactions sync --max-pages 10
# Beeper, with Beeper Desktop running
ghostget auth add beeper-main --linked-device beeper --device-store ~/.beeper
ghostget auth bind beeper-main --site beeper
peopleblade beeper sync
# WhatsApp, paired as a linked device
ghostget auth add whatsapp-main --linked-device whatsapp
ghostget auth pair whatsapp-main
ghostget auth sync whatsapp-main --once
peopleblade whatsapp sync
# Substack, from a browser signed in as the publication's owner
ghostget auth add substack-main --cookie-source chrome --cookie-profile '<profile from ghostget browsers>'
ghostget auth bind substack-main --site substack
peopleblade substack status
peopleblade substack sync --publication NAMESubstack sync handles publications up to 500 subscribers, and it imports the list only when the export is complete. peopleblade substack status checks the GhostGet setup without calling Substack. Beeper also needs the Beeper CLI; GhostGet's Beeper guide at ghostget.com/docs/how-to/connect-beeper covers it.
Import a contact file
Import a UTF-8 CSV or vCard file on macOS or Linux. Use a private regular file owned by you, up to 16 MiB and 25,000 records. Initialize your book first, then preview the import before saving it.
chmod 600 /private/path/contacts.csv
peopleblade contacts import /private/path/contacts.csv --account personal-export --preview --json
# vCard 3.0 or 4.0
peopleblade contacts import /private/path/contacts.vcf --format vcard --account address-book --preview --json
# Outlook CSV with supported English headings
peopleblade contacts import /private/path/outlook.csv --format outlook-csv --account outlook --preview --jsonThe default CSV header accepts any subset of id, name, given_name, family_name, email, phone, organization, title, birthday, and profile_url. Each row needs an ID, email, or international phone such as +12025550123. Use one email and one phone per cell. Birthdays use YYYY-MM-DD or --MM-DD. Unknown columns are rejected; quoted commas and line breaks are supported.
Apply the same private-file permissions to vCard and Outlook files. vCard photos and notes are ignored. Outlook imports use supported English export headings and discard unsupported columns; localized headings are not guessed.
Remove --preview to save the contact details. Keep the same --account label for updates from the same source, and prefer a stable ID for each CSV row. Imports preserve omitted records and leave identity matches for review. A preview does not write to the book or reserve its state; later edits can change the import result.
Accept matches without losing their sources
peopleblade identity suggest --limit 25 --json
peopleblade identity decide TOKEN accept --note "reviewed exact evidence" --json
# Only to reverse that accepted decision:
peopleblade identity separate DECISION_ID --jsonKeep the decisionId from the identity decide result. Use that ID if you later choose to separate the two records; do not rely on a filtered listing to recover it.
Read the evidence before accepting a fresh decision token. Similar names, employers, or a shared household phone number do not justify a merge. Accepting a match shows the two records as one person. The original records stay unchanged, and separating them undoes the join.
# Overlap counts, not the complete decision history
peopleblade identity audit --json
peopleblade identity decisions --jsonThe audit reports how many records share an observed email or phone. The decisions command lists accepted observed-email and observed-phone decisions only; exact-email and exact-phone decisions are not included.
Interaction totals account for overlapping sources. Treat them as a lower bound on how often you've been in touch, not a complete message history or a measure of how close you are.
Find and inspect a person
peopleblade capabilities --json
peopleblade query --search "Ada" --sort name --direction asc --limit 50 --json
peopleblade people show 12 --jsonQuery searches names, companies, titles, active contact methods, and provider handles. Filter by source, email or phone presence, and do-not-contact status. Search punctuation is literal, not SQL wildcard syntax. Use the source facet keys from the result, not capability identifiers.
Each page of results returns total, offset, limit, and nextOffset. Pass nextOffset as --offset to continue. Pages are a live view: imports and identity decisions can move rows between requests, so restart at offset zero after changes. Other list commands keep their own output shape.
The capabilities command lists supported sources and interfaces without opening a database or the network. It does not prove that a tool, credential, permission, or provider is configured. Person details include totals and truncation markers; a displayed contact value is not by itself evidence for an identity join.
Edit notes with a recoverable history
peopleblade notes list --person-id 12 --json
peopleblade notes show 42 --json
peopleblade notes update 42 --expected-revision 0 \
--expected-context CONTEXT_SHA256 --request-id REQUEST_UUID \
--body-file /private/path/note.md --title "Follow-up" --json
peopleblade notes history 42 --jsonUse the current revision and context digest from notes show and a fresh UUID for each new save. --body-file - reads the note from stdin, so private note text need not appear in shell arguments. Use command help for the option that clears a title.
Edits add a new revision without replacing imported content, occurrence dates, or the record of where each note came from. Search uses current content; history keeps earlier versions. Restoring old text creates another revision.
If the content, attribution, or identity changes while you edit, keep your draft and reload before saving. After an uncertain network result, retry with the same request UUID and the same payload; do not invent a second save.
Notes and their history never go into the contact projection, public research, or the background file for your agent. Device sync carries them to your other devices, end-to-end encrypted. Keep exported drafts private too.
Organize the book and follow up
peopleblade people edit 12 --organization "New Co" --json
peopleblade tags add 12 investor --json
peopleblade query --tag investor --json
peopleblade searches save investors --tag investor --sort last-contact --jsonpeople edit keeps your correction in a separate layer, so a later source import never overwrites it; --reset restores the imported value. Tags label people for query --tag, and searches save keeps a named filter for searches run.
peopleblade people cadence 12 30d --json
peopleblade reminders add 12 --due 1w --text "Send intro" --json
peopleblade reminders due --json
peopleblade people timeline 12 --jsonA cadence says how often you want to be in touch, and reminders due lists dated follow-ups and people past their cadence, counted from the last recorded interaction or dated note. people do-not-contact keeps someone out of due lists unless you pass --include-do-not-contact. The timeline combines notes, reminders, your edits, calendar invitations, and interaction metadata, never message text. Nothing notifies you; you or your agent run the command.
Research a person with your own agent
- Begin with your own sources and official exports; review exact identity overlaps before adding claims.
- Prepare public research for one selected person. You or your agent supply reviewed citations, or abstain. PeopleBlade does not call a provider in this local workflow; the agent's search and model tools may charge separately.
peopleblade research prepare PERSON_ID > /private/path/research.json
# Fill only result with reviewed public citations, or abstain
peopleblade research apply /private/path/research.json --jsonKeep the template's subject and instructions intact. Each saved public claim needs a citation. Research does not authorize contacting anyone, collecting signed-in social graphs, or expanding a provider's permissions.
An agent can work through the book in batches: research candidates ranks the contacts with enough anchors to research, research attest runs free public checks (Gravatar, GitHub, Keybase, Wikidata, SEC EDGAR, OpenAlex, and the Wayback Machine's record of a stored LinkedIn URL) for one person and records what matches as cited evidence, research sweep does the same for a ranked batch and can write an apply-ready draft, and research apply stores a reviewed batch file after a dry run. Every command can print JSON.
peopleblade research candidates --limit 20 --json
peopleblade research attest PERSON_ID --json
peopleblade research sweep --limit 20 --jsonBrief your agent on one person
Choose one person, review their background and cited public research, and decide which agent environment may receive the result. Creating the file does not send it to an agent or give an agent access to your contact book.
peopleblade soulscrape prepare PERSON_ID --output /private/path/person.ensoul-source.json --jsonThe background file is private, readable only by you, and holds one person's background and their current cited public research. It leaves out your notes, message text, raw source records, your other contacts, public-email guesses, and the exact email addresses, phone numbers, and account handles you store for that person.
Creating the file needs only the CLI. Soulscrape checks each file before it reads it and ignores a file that fails the check.
A checked file is still source material, not consent, proof of identity, a voice profile, or permission to contact or act for anyone. Share it only with the person or agent environment you authorized.
Sync the book between your devices (optional)
# on the first device:
peopleblade cloud signin
peopleblade sync enable --recovery-key-out /private/path/recovery-key.txt
# store that file somewhere safe; it is the only key backup
# on each new device, after its own cloud signin:
peopleblade init
peopleblade sync join # shows a six-digit code
# then, on a device you already trust:
peopleblade sync approve REQUEST_ID --code 123456
peopleblade sync nowDevice sync replicates your whole book between your computers: contacts and their details, notes and note history, reminders, tags, exposure findings, Photos evidence links, identity decisions, source records, and research results. Every change travels inside an end-to-end encrypted envelope sealed on the sending device, and the server keeps only the ciphertext with its size, timestamp, device and key IDs, sync positions, the joining device's name, the pairing public keys, and the book key wrapped for each device. It cannot read the contents.
A new device asks for approval with a six-digit code that a device you already trust confirms with sync approve; it then restores the book from an encrypted snapshot and stays in sync with sync now. A new device that already has contacts merges its book into the account; sync join --dry-run previews that merge without writing anything. The recovery key is the only other way in: sync join --recovery-key - reads it from standard input, and it is never stored by the CLI or the server. Losing the recovery key while no enabled device remains makes the encrypted copy unrecoverable.
Edits on two devices merge per field by last write wins, with tombstones for deleted rows. peopleblade sync status shows this device's state and pending changes, sync disable turns sync off here, and cloud revoke DEVICE_ID removes a device on the server so it stops receiving envelopes. Provider credentials and provider account bindings stay on each device and are not synced.
Cloud sync: contact details for agents (optional)
peopleblade cloud signin
peopleblade cloud syncCloud sync uploads the contact projection: a copy of your contact details on your PeopleBlade account. It is separate from device sync and is not end-to-end encrypted. Run it only when you want an agent platform or hosted research to reach your contacts. It uploads every contact's synced fields: names, organizations, titles, birthdays, email addresses, phone numbers, profile URLs and account handles, interaction counts and dates, and source names. It uploads no notes, note revisions, exposure findings, Photos evidence, message text, archives, local paths, or provider credentials.
The account page on peopleblade.com shows synced totals and the devices you have approved, and downloads every synced contact as CSV. There is no web contact list. CSV prefixes cells that look like spreadsheet formulas with an apostrophe; use JSON when exact string bytes matter.
The CLI's own hosted routes are device-authenticated, not a public contact API. Agent platforms that cannot run the CLI use /api/v1, described by /api/v1/openapi.json: a device you approve can read your synced contacts, export them as CSV, and preview hosted research, and you can revoke it at any time. There is no anonymous contact API, MCP server, GraphQL endpoint, or OAuth application.
Hosted research (optional)
Hosted research runs on PeopleBlade's servers for contacts you uploaded with cloud sync. Each run searches the public web for one person and saves a detail only when its source matches something you already hold, such as a profile URL or work email, with the citation. The privacy page names the services it uses.
Hosted research is optional and costs $0.16 per contact. Previewing a run is free and shows the contacts it would research. You pay only for contacts where a run saves at least one detail. Credits are prepaid, one credit per cent, in packs of $10, $25, $50, or $100, and you pay through Stripe Checkout.
peopleblade cloud signin
peopleblade cloud sync
# Preview: no charge
peopleblade cloud enrich --person-id ID --json
# Run: repeat the IDs with the confirmation from the preview
peopleblade cloud enrich --confirm TOKEN --person-id IDSign in registers this computer with your web account, and cloud sync uploads the contact projection described above. The preview lists the contacts a run would research, changes nothing, and returns a confirmation that expires after ten minutes. If your prepaid credits do not cover the run, the command stops before any work starts and prints a link to add credits; peopleblade credits status shows your balance, and peopleblade credits estimate enrich_contact --units N prices a batch.
Hunter is an optional fallback for a work email. It never replaces identity evidence or the local book, and PeopleBlade never stores a guessed address as fact.
Optional updates and support
PeopleBlade offers optional product updates and paid support, and no feature depends on either. peopleblade support protocol --json prints when an agent may mention them, and HRANESS_SUPPORT=off turns off these notices and offers.
Back up before larger changes
peopleblade backupSchema upgrades create a private backup before applying migrations. Make another before a large import or identity-review session. Keep the original database and backup until any restored copy passes integrity and data checks, and never replace a database while the CLI has it open.
Treat contact JSON, notes, backups, and background files as private data, even when they contain no credentials.