network-scan
Scan your LinkedIn contacts' companies for matching job openings
What this skill does
# Network Scan Skill
> **Priority hierarchy**: See `shared/references/priority-hierarchy.md` for 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.
## Quick Start
- `/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+)
## File Structure
```
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
```
---
## Workflow
### Step 0: Check Prerequisites
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)
### Step 1: Select Contacts & Extract Companies
Parse `$ARGUMENTS`:
- If a number (e.g., `50`): use that as the contact limit
- If `all`: use all contacts (warn user this may be slow if > 200)
- If empty/missing: default to 25
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..."
### Step 2: Resolve Careers Pages (Parallelized)
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:
- **Cached (fresh)**: `last_checked` within last 7 days - use as-is, no work needed
- **Cached (stale)**: `last_checked` older than 7 days - needs re-verification
- **Uncached**: not in cache, or `type` is `"not_found"` and stale - needs full resolution
Report: "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:
- A batch of company names to resolve
- Instructions from `scripts/resolve-careers.md`
Each subagent uses `WebSearch` (NOT the browser) to find careers pages:
1. Search: `"[Company Name]" careers jobs site:[company domain if known]`
2. From the search results, identify the careers/jobs page URL
3. Classify the URL type:
- `"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)
4. Return results for the batch
Collect results from all subagents and merge into the cache. Save `~/.proficiently/company-careers.json`. Format:
```json
{
"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."
### Step 3: Scan for Matching Jobs (Parallelized)
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:
- A batch of companies (name, careers_url, ATS type, network contacts)
- Candidate profile summary (from resume)
- Preferences (target roles, must-haves, dealbreakers, nice-to-haves)
- Instructions from `scripts/evaluate-company.md`
Each subagent:
1. Creates its own browser tab (`tabs_context_mcp` then `tabs_create_mcp`)
2. For each company in its batch:
a. Navigate to the careers page
b. Search/browse for roles matching target roles and keywords
c. For ATS pages, use platform search/filter functionality:
- **Greenhouse**: search box or department filters
- **Lever**: search bar or team filter
- **Workday**: keyword search field
- **Direct/other**: browse the page, use any search, scan listed roles
d. Extract listings: title, location, URL
e. Score each listing (High/Medium/Low/Skip per fit criteria)
f. Return only High and Medium fits
3. Returns results for its entire batch
**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.
### Step 4: Save Results
**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:
```markdown
# Network Scan History
This file tracks all network scans run by the `/network-scan` skill.
---
```
Then append:
```markdown
## 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:
```markdown
# [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]
```
### Step 5: Present Results
Show matches grouped by fit, with contact info for warm introductions:
```markdown
## 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**: MediuRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.