pp-contact-goat — Claude Code skill: what it does, how to install
Terminal-based prospecting, warm-intro mapping, and profile enrichment across LinkedIn, Happenstance, and Deepline.
npx skills add mvanhorn/printing-press-library --skill pp-contact-goat -a claude-codeWhat pp-contact-goat does
This skill directs the contact-goat-pp-cli binary to discover and map professional relationships inside your coding agent. It checks relationship coverage across target companies, discovers mutual connections to build warm-intro paths, and aggregates records from LinkedIn, Happenstance, and Deepline into a single dossier.
Happenstance integration combines two authentication paths. The CLI auto-prefers Chrome session cookies to consume free monthly allocations first. When that quota runs out, it falls back to the REST API via HAPPENSTANCE_API_KEY, spending 2 credits per search and 1 credit per research dossier. Supplying the --agent flag formats output into compact JSON without ANSI coloring or prompts.
Commands stop working if contact-goat-pp-cli is missing from $PATH. Running Deepline waterfall enrichment or email lookups also strictly requires setting DEEPLINE_API_KEY.
What it helps with
- map warm-intro paths to target executives through mutual connections
- inspect company relationship coverage ranked by connection strength
- compile dossiers across LinkedIn, Happenstance, and Deepline profiles
- run waterfall enrichment that checks free quotas before paid APIs
Example prompts for the agent
- Who do I know at Stripe, and what is the best warm-intro path to their VP of Eng?
- Build a dossier on Alex Smith at Acme Corp using LinkedIn and Happenstance
- Run waterfall enrichment on this prospect list using free sources first
How to install pp-contact-goat
1Skills CLI (Vercel)
npx skills add mvanhorn/printing-press-library --skill pp-contact-goat -a claude-code2Manually: put the files in place
~/.claude/skills/pp-contact-goat/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/pp-contact-goat/
1Skills CLI (Vercel)
npx skills add mvanhorn/printing-press-library --skill pp-contact-goat -a codex2Manually: put the files in place
.agents/skills/pp-contact-goat/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add mvanhorn/printing-press-library --skill pp-contact-goat -a cursor2Manually: put the files in place
.cursor/skills/pp-contact-goat/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install mvanhorn/printing-press-library pp-contact-goat2Manually: put the files in place
.github/skills/pp-contact-goat/SKILL.md1Skills CLI (Vercel)
npx skills add mvanhorn/printing-press-library --skill pp-contact-goat -a gemini-cli2Platform CLI
gemini skills install https://github.com/mvanhorn/printing-press-library --path cli-skills/pp-contact-goatManually: put the files in place
.devin/skills/pp-contact-goat/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add mvanhorn/printing-press-library --skill pp-contact-goat -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about pp-contact-goat
How to install pp-contact-goat in Claude Code?
Add the skill by running npx skills add mvanhorn/printing-press-library --skill pp-contact-goat -a claude-code. Then install the underlying CLI binary with npx -y @mvanhorn/printing-press-library install contact-goat --cli-only and confirm the binary location is exported to your $PATH.
What does pp-contact-goat do?
It enables terminal-based prospecting, connection mapping, and multi-source profile enrichment using LinkedIn, Happenstance, and Deepline.
What credentials are required to use pp-contact-goat?
Basic Happenstance queries run on local Chrome cookies, while HAPPENSTANCE_API_KEY serves as fallback or research auth. Deepline operations require exporting DEEPLINE_API_KEY.
Source text
SKILL.md · Apache-2.0
---
name: pp-contact-goat
description: "Super LinkedIn for the terminal. Search, enrich, and map warm-intro paths across LinkedIn (stickerdaniel/linkedin-mcp-server subprocess), Happenstance (cookie-first free quota with bearer-API fallback), and Deepline (paid enrichment). Two Happenstance auth surfaces coexist: Chrome cookie session (free monthly allocation) and HAPPENSTANCE_API_KEY bearer (paid credits, deeper schema). Use when the user asks who they know at a company, how to get a warm intro, who to prospect, or wants cross-source dossiers, network diffs, or waterfall enrichment."
author: "Matt Van Horn"
license: "Apache-2.0"
argument-hint: "<command> [args] | install cli|mcp"
allowed-tools: "Read Bash"
metadata:
openclaw:
requires:
bins:
- contact-goat-pp-cli
install:
- kind: go
bins: [contact-goat-pp-cli]
module: github.com/mvanhorn/printing-press-library/library/sales-and-crm/contact-goat/cmd/contact-goat-pp-cli
---
<!-- GENERATED FILE — DO NOT EDIT.
This file is a verbatim mirror of library/sales-and-crm/contact-goat/SKILL.md,
regenerated post-merge by tools/generate-skills/. Hand-edits here are
silently overwritten on the next regen. Edit the library/ source instead.
See the repository agent guide, section "Generated artifacts: registry.json, cli-skills/". -->
# Contact Goat - Printing Press CLI
## Prerequisites: Install the CLI
This skill drives the `contact-goat-pp-cli` binary. **You must verify the CLI is installed before invoking any command from this skill.** If it is missing, install it first:
1. Install via the Printing Press installer. It defaults binaries to `$HOME/.local/bin` on macOS/Linux and `%LOCALAPPDATA%\Programs\PrintingPress\bin` on Windows:
```bash
npx -y @mvanhorn/printing-press-library install contact-goat --cli-only
```
2. Verify: `contact-goat-pp-cli --version`
3. Ensure the reported install directory is on `$PATH` for the agent/runtime that will invoke this skill.
If the `npx` install fails (no Node, offline, etc.), fall back to a direct Go install (requires Go 1.26.6 or newer):
```bash
go install github.com/mvanhorn/printing-press-library/library/sales-and-crm/contact-goat/cmd/contact-goat-pp-cli@latest
```
If `--version` reports "command not found" after install, the runtime cannot see the binary directory on `$PATH`. Do not proceed with skill commands until verification succeeds.
## When to Use This CLI
Reach for this when the user wants:
- coverage of a company (who you already know there, ranked by relationship strength)
- a warm-intro path to a target person (mutual connections across sources)
- prospecting (fan-out search with cross-source dedupe)
- a unified dossier (LinkedIn profile + Happenstance research + optional Deepline enrichment)
- network diffs over time (what's new in your graph in the last N days)
- waterfall enrichment that walks free sources before paid ones
Skip it when the user has a workflow that lives entirely inside LinkedIn Sales Navigator, or when they only need raw LinkedIn scraping with no Happenstance or Deepline overlay (use the LinkedIn MCP directly in that case).
## Two Auth Surfaces
Happenstance has two parallel auth paths and the CLI uses both:
| Surface | Auth | Cost | Default? |
|---------|------|------|----------|
| Cookie web app | Chrome session cookies | Free monthly allocation | YES (auto-prefer) |
| Public REST API | HAPPENSTANCE_API_KEY (Bearer) | 2 credits/search, 1 credit/research | Fallback only |
The auto router prefers cookies until quota is exhausted, then falls back to bearer with an explicit "cost spent" log line on stderr. Use `--source api` on `coverage`, `hp people`, `prospect`, or `warm-intro` to opt into bearer explicitly (e.g. for the richer research schema or scoped group searches). Use `--source hp` to force the cookie surface.
The `api hpn *` subcommands always use the bearer surface and always cost credits. Provision and rotate keys at https://happenstance.ai/settings/api-keys.
## Argument Parsing
Parse `$ARGUMENTS`:
1. Empty, `help`, or `--help` -> run `contact-goat-pp-cli --help`
2. Starts with `install` and ends with `mcp` -> MCP installation (see below)
3. Starts with `install` -> CLI installation (see below)
4. Anything else -> Direct Use (map the request to the best command and run it)
## MCP Server Installation
1. Install the MCP server:
```bash
go install github.com/mvanhorn/printing-press-library/library/sales-and-crm/contact-goat/cmd/contact-goat-pp-mcp@latest
```
2. Register with Claude Code:
```bash
claude mcp add -e DEEPLINE_API_KEY=value -e HAPPENSTANCE_API_KEY=value contact-goat-pp-mcp -- contact-goat-pp-mcp
```
Ask the user for actual values of required API keys before running.
3. Verify: `claude mcp list`.
The MCP server exposes 16 tools. The four bearer-API tools added in this release are:
- `api_search` - Run a Happenstance public-API search (costs 2 credits)
- `api_research` - Run a deep-research dossier (costs 1 credit on completion)
- `api_groups_list` - List Happenstance groups for the caller (free)
- `api_usage` - Show live credit balance and usage history (free)
The other 12 tools cover the cookie surface (search, friends, feed, notifications, dossier, etc.) and the LinkedIn / Deepline integrations.
## Direct Use
1. Check if installed: `which contact-goat-pp-cli`. If not found, offer CLI installation (above).
2. Discover commands: `contact-goat-pp-cli --help`. Drill into subcommand help with `contact-goat-pp-cli <command> --help` or `contact-goat-pp-cli api hpn <subcommand> --help`.
3. Match the user query to the best command (see Notable Commands below).
4. Execute with the `--agent` flag for structured, token-efficient output:
```bash
contact-goat-pp-cli <command> [args] --agent
```
5. The `--agent` flag sets `--json --compact --no-input --no-color --yes`.
Source routing (cookie vs bearer) is automatic. The auto router prefers the free cookie surface and falls back to the paid bearer surface only when cookie quota is exhausted, logging a "cost spent" notice on stderr. Pass `--source api` to opt into bearer explicitly (richer schema, group-scoped searches), or `--source hp` to force cookies.
## Enrichment Preflight (read this before running any enrichment command)
These commands spend Deepline credits and REQUIRE `DEEPLINE_API_KEY` or a BYOK setup:
- `waterfall` (unless you pass `--byok` and have BYOK providers configured)
- `dossier --enrich-email`
- `deepline find-email` / `enrich-person` / `email-find` / `phone-find`
- `deepline search-people` / `search-companies` / `enrich-company`
Before invoking any of these, verify auth by running doctor first:
```bash
contact-goat-pp-cli doctor --agent | grep -i deepline
```
`deepline_env` shows the resolution source:
- `set (env)` — `DEEPLINE_API_KEY` exported in the current shell
- `set (flag)` — `--deepline-key` passed on the command line
- `set (file:~/.local/deepline/<host>/.env)` — auto-discovered from the official Deepline CLI's persisted key (the user authenticated with `deepline auth register` or `deepline auth status`; no shell export needed)
- `not set` — none of the above. Ask the user for a key, or for a BYOK Hunter/Apollo key
The auto-discovery path means a user who has the Deepline CLI installed and authenticated does NOT need to re-export the key into their shell — contact-goat reads `~/.local/deepline/code-deepline-com/.env` directly (mode 0600, owned by the user). Don't ask the user to re-export when `set (file:...)` is reported. If `deepline_discovery_skipped` is also reported, those are candidate files the resolver rejected for a security reason (wrong mode, missing prefix); surface them so the user can fix the underlying issue.
Provider chain by target kind (waterfall):
| Target | Primary | Fallback 1 | Fallback 2 |
|--------|---------|-----------|-----------|
| LinkedIn URL | apollo_people_match | hunter_people_find | contactout_enrich_person |
| Email | apollo_people_match | hunter_people_find | - |
| Name + --company | dropleads_email_finder | hunter_email_finder | datagma_find_email |
Notes:
- Name targets MUST pass `--company <domain>` (or set `CONTACT_GOAT_COMPANY` env).
- Apollo returns `personal_emails[]` when available; treat `email_status: "unavailable"` as "no verified work email on file" (the personal email is still usable).
- Dropleads returns `status: "catch_all"` for domains on Google Workspace; the email is a pattern guess, not a verified mailbox.
- Provider-level 403s are surfaced as "Provider not connected" rather than "Check DEEPLINE_API_KEY"; they do not abort the chain. The next provider is tried automatically.
## Notable Commands
| Command | What it does |
|---------|--------------|
| `coverage <company>` | Who you know at a company across LinkedIn + Happenstance, ranked by relationship strength |
| `coverage --location <city>` | Who you know in a city. Bearer-only (cookie surface has no city-search); use `--source api`. |
| `hp people <query>` | Happenstance graph people-search (1st / 2nd / 3rd degree). `--csv` emits flat CSV with semicolon-joined bridges. |
| `prospect <query>` | Fan-out search across LinkedIn + Happenstance (+ opt-in Deepline), deduped |
| `warm-intro <target>` | Mutual connections across sources who could intro you to a target |
| `waterfall <target> [--company X]` | Free-sources-first enrichment, falls through to Deepline provider chain. Requires DEEPLINE_API_KEY or --byok. Bare-name targets need --company |
| `dossier <target> [--enrich-email]` | Unified LinkedIn + Happenstance + (optional) Deepline dossier. --enrich-email requires DEEPLINE_API_KEY |
| `deepline find-email "<name>" --company <domain>` | Single-call work-email lookup via dropleads_email_finder |
| `deepline enrich-person <linkedin-url>` | Full person record via apollo_people_match (includes personal_emails[]) |
| `api hpn search <text>` | Bearer-API search (costs 2 credits, async with poll). `--first-degree-only` keeps only 1st-degree matches; `--min-score N` drops weak signals (see docs/scoring.md); `--all --max-results N` auto-paginates. |
| `api hpn research <description>` | Bearer-API deep dossier (costs 1 credit on completion) |
| `api hpn usage` | Live credit balance, purchases, recent usage events (free) |
| `doctor` | Check CLI health, both Happenstance surfaces, LinkedIn, and Deepline. Reports `happenstance_graph_status` (ok / stale / very_stale) on the LinkedIn upload age. |
Run any command with `--help` for full flag documentation.
## Agent Mode
Add `--agent` to any command. Expands to: `--json --compact --no-input --no-color --yes`.
- **Pipeable** — JSON on stdout, errors on stderr
- **Filterable** — `--select` keeps a subset of fields, with dotted-path support (see below)
- **Previewable** — `--dry-run` shows the request without sending
- **Cacheable** — GET responses cached for 5 minutes, bypass with `--no-cache`
- **Non-interactive** — never prompts, every input is a flag
### Filtering output
`--select` accepts dotted paths to descend into nested responses; arrays traverse element-wise:
```bash
contact-goat-pp-cli <command> --agent --select id,name
contact-goat-pp-cli <command> --agent --select items.id,items.owner.name
```
Use this to narrow huge payloads to the fields you actually need — critical for deeply nested API responses.
### Response envelope
Data-layer commands wrap output in `{"meta": {...}, "results": <data>}`. Parse `.results` for data and `.meta.source` to know whether it's `live` or local. The `N results (live)` summary is printed to stderr only when stdout is a TTY; piped/agent consumers see pure JSON on stdout.
## Exit Codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 2 | Usage error (wrong arguments) |
| 3 | Resource not found |
| 4 | Authentication required |
| 5 | API error (upstream issue, including bearer 402 out-of-credits) |
| 7 | Rate limited (cookie 429 or bearer 429; auto-fallback may apply) |
© Matt Van Horn · Apache-2.0 · mvanhorn/printing-press-library