Scan your LinkedIn contacts' companies for matching job openings
Priority hierarchy: See
shared/references/priority-hierarchy.mdfor conflict resolution.
Proactively check whether companies where you know someone are hiring for roles that match you. First run builds a cache of company careers page URLs. Subsequent runs reuse the cache, making weekly checks fast.
/proficiently:network-scan - Scan companies from your 25 most recent contacts/proficiently:network-scan 50 - Check the 50 most recent contacts/proficiently:network-scan all - Check all contacts (can be slow with 1500+)scripts/
resolve-careers.md # Subagent for resolving a batch of company careers URLs
evaluate-company.md # Subagent for scanning a batch of companies' open roles
User data (stored at ~/.proficiently/):
~/.proficiently/
resume/ # Your resume PDF/DOCX
preferences.md # Job matching rules
profile.md # Work history from interview
linkedin-contacts.csv # LinkedIn contacts export
company-careers.json # Cached company careers URLs
network-scan-history.md # Running log of scan results
jobs/ # Per-job application folders
Resolve the data directory, then check prerequisites per shared/references/prerequisites.md. Resume, preferences, and linkedin-contacts.csv are all required.
Load these files for use in later steps:
DATA_DIR/preferences.md (target roles, must-haves, dealbreakers, nice-to-haves)DATA_DIR/resume/* (candidate profile)DATA_DIR/profile.md (work history, if it exists)Parse $ARGUMENTS:
50): use that as the contact limitall: use all contacts (warn user this may be slow if > 200)Read ~/.proficiently/linkedin-contacts.csv. Sort by "Connected On" descending (most recent first). Take the first N contacts based on the limit.
Extract unique company names from the selected contacts. Skip companies with empty or blank names.
Group contacts by company into a lookup:
{
"Google": [{"name": "Jane Smith", "position": "PM Director", "url": "https://linkedin.com/in/janesmith"}, ...],
"Stripe": [{"name": "John Doe", "position": "Eng Manager", "url": "https://linkedin.com/in/johndoe"}]
}
Report to user: "Found X unique companies from Y contacts. Checking careers pages..."
Load ~/.proficiently/company-careers.json if it exists (the cache). If it doesn't exist, start with an empty object.
Split companies into three groups:
last_checked within last 7 days - use as-is, no work neededlast_checked older than 7 days - needs re-verificationtype is "not_found" and stale - needs full resolutionReport: "X companies from cache, Y need resolution..."
Parallel resolution using subagents:
Take all companies needing resolution (stale + uncached) and split them into batches of 10. Spawn one subagent per batch using the Task tool (subagent_type: "general-purpose"). Run all batches in parallel.
Each subagent receives:
scripts/resolve-careers.mdEach subagent uses WebSearch (NOT the browser) to find careers pages:
"[Company Name]" careers jobs site:[company domain if known]"direct" - company's own careers page (e.g., careers.google.com)"greenhouse" - Greenhouse ATS (boards.greenhouse.io/company or company.greenhouse.io)"lever" - Lever ATS (jobs.lever.co/company)"workday" - Workday ATS (company.wd5.myworkdayjobs.com)"other_ats" - other ATS platforms (Ashby, BambooHR, etc.)"not_found" - no careers page could be found (set careers_url to null)Collect results from all subagents and merge into the cache. Save ~/.proficiently/company-careers.json. Format:
{
"Company Name": {
"careers_url": "https://careers.example.com",
"type": "direct",
"last_checked": "YYYY-MM-DD",
"last_found_roles": 0
}
}
Report progress: "Resolved X new careers pages, Y from cache, Z not found."
Take all companies with a valid careers_url (skip not_found and ignored entries). Split them into batches of 5 companies each.
Spawn parallel subagents using the Task tool (subagent_type: "general-purpose"). Run all batches in parallel (up to 5 concurrent subagents to avoid overwhelming the browser).
Each subagent receives:
scripts/evaluate-company.mdEach subagent:
tabs_context_mcp then tabs_create_mcp)Fit scoring criteria: See shared/references/fit-scoring.md for the canonical definitions.
Collect results from all subagents. Update last_found_roles count in the cache for each company scanned.
If a subagent fails or times out, log the companies it was processing and move on. Do not retry - the user can re-run with those companies next time.
Update company-careers.json:
Update last_checked and last_found_roles for every company that was scanned.
Append to ~/.proficiently/network-scan-history.md:
If the file doesn't exist, create it with:
# Network Scan History
This file tracks all network scans run by the `/network-scan` skill.
---
Then append:
## YYYY-MM-DD - Network Scan (N contacts, M companies)
| Company | Contact | Role Found | Fit | URL |
|---------|---------|------------|-----|-----|
| Google | Jane Smith (PM Director) | Sr. Product Manager | High | https://... |
| Stripe | John Doe (Eng Manager) | No matching roles | - | - |
Include all companies scanned (both matches and non-matches) in the table.
Save full postings for High-fit matches:
For each High-fit match, navigate to the job posting URL and save the full posting to ~/.proficiently/jobs/[company-slug]-[YYYY-MM-DD]/posting.md using the standard format:
# [Job Title] - [Company Name]
**Company**: [Company]
**Location**: [Location]
**Salary**: [Salary or N/A]
**Type**: [Type]
**Source**: network-scan
**Date Found**: YYYY-MM-DD
**Network Contact**: [Contact Name] ([Position]) - [LinkedIn URL]
## About the Role
[Description]
## Key Requirements
- [requirement]
## Direct Careers Page
- [URL]
## Fit Assessment
**Rating**: [High/Medium]
**Why**: [explanation]
Show matches grouped by fit, with contact info for warm introductions:
## Network Scan Results - YYYY-MM-DD
Scanned N companies from M contacts.
### Matches Found
#### 1. Senior Product Manager at Google
- **Fit**: High
- **Your contact**: Jane Smith (PM Director) - [LinkedIn](url)
- **Location**: Mountain View, CA
- **Apply**: https://careers.google.com/jobs/...
- **Why**: [brief match reason]
#### 2. Strategy Lead at Stripe
- **Fit**: Medium
- **Your contact**: John Doe (Eng Manager) - [LinkedIn](url)
- **Location**: Remote
- **Apply**: https://stripe.com/jobs/...
- **Why**: [brief match reason]
### Companies Checked (No Matches)
Google (3 open roles, none matching), Stripe (0 open roles), ...
### Companies Without Careers Pages
Acme Corp, Small Startup LLC, ...
If no matches were found across all companies:
## Network Scan Results - YYYY-MM-DD
Scanned N companies from M contacts. No matching roles found this time.
### Companies Checked
[List with role counts]
### Companies Without Careers Pages
[List]
Try again next week, or expand your search: `/proficiently:network-scan 100`
End with:
To tailor a resume: /proficiently:tailor-resume [job URL]
To write a cover letter: /proficiently:cover-letter [job URL]
Built by Proficiently. Want someone to find jobs, tailor resumes,
apply, and connect you with hiring managers? Visit proficiently.com
If the user provides feedback after seeing results:
"ignored": true to that company's entry in company-careers.json. Future scans will skip it.~/.proficiently/preferences.md accordingly (e.g., "add fintech to nice-to-haves", "no crypto companies").Structure user-facing output with these sections:
/proficiently:tailor-resume and /proficiently:cover-letter for top matchesAdd to ~/.claude/settings.json:
{
"permissions": {
"allow": [
"Read(~/.claude/skills/**)",
"Read(~/.proficiently/**)",
"Write(~/.proficiently/**)",
"Edit(~/.proficiently/**)",
"mcp__claude-in-chrome__*"
]
}
}