About freelance-gig-finder
A skill for searching recent freelance and contract listings across multiple job platforms based on a user’s skills. It guides parallel searches, filtering, and deduplication, and requires TinyFish CLI installation and authentication.
Key features
- 01Searches five job platforms
- 02Runs platform searches in parallel
- 03Filters listings by recency
- 04Deduplicates cross-platform results
- 05Requires TinyFish CLI and authentication
Use cases
- 01Find recent gigs matching a professional skill
- 02Compare contract listings across platforms
- 03Narrow results by budget or location
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ tinyfish-io/ tinyfish-cookbook --skill freelance-gig-finderAfter installing, type/freelance-gig-finderin Claude Code to confirm it loaded.
Details
From the project READMEFreelance Gig Finder
Search Upwork, Contra, We Work Remotely, Freelancer, and Toptal simultaneously for fresh freelance and contract opportunities matching your skill set — filtered to recent postings so you're not looking at stale listings.
Pre-flight Check (REQUIRED)
Before making any TinyFish call, always run BOTH checks:
1. CLI installed?
which tinyfish && tinyfish --version || echo "TINYFISH_CLI_NOT_INSTALLED"
If not installed, stop and tell the user:
Install the TinyFish CLI:
npm install -g @tiny-fish/cli
2. Authenticated?
tinyfish auth status
If not authenticated, stop and tell the user:
You need a TinyFish API key. Get one at: https://agent.tinyfish.ai/api-keys
Then authenticate:
tinyfish auth login
Do NOT proceed until both checks pass.
Step 1 — Gather inputs
You need:
- Skill or role — e.g.
React developer,Python,UI/UX designer,copywriter,DevOps,mobile developer - Budget preference (optional) — e.g.
hourly,fixed price,$50+/hr - Recency (optional) — default to listings posted in the last 7 days
If skill is not provided, ask before proceeding.
Step 2 — Parallel search
Fire all agents simultaneously.
# Agent 1 — Upwork
tinyfish agent run \
--url "https://www.upwork.com/nx/search/jobs/?sort=recency&q={SKILL_ENCODED}" \
"You are on Upwork job search results for '{SKILL}', sorted by most recent.
Extract the first 8 visible job listings.
For each listing extract:
- title
- client description snippet (what they need)
- budget (hourly rate range or fixed price if shown)
- posted time (e.g. '2 hours ago', 'yesterday')
- required skills listed
- job type (hourly/fixed)
- direct URL to the listing
STRICT RULES:
- Do NOT click any listing
- Read only what is visible in the search result cards
- Only include listings posted within the last 7 days
- Maximum 8 listings then stop
Return JSON array: [{title, description, budget, posted, skills: [], job_type, url}]" \
--sync > /tmp/fg_upwork.json &
# Agent 2 — Contra
tinyfish agent run \
--url "https://contra.com/opportunities?query={SKILL_ENCODED}&sort=recent" \
"You are on Contra job listings for '{SKILL}', sorted by newest.
Extract the first 8 visible job listings.
For each listing extract:
- title
- client/company name
- description snippet
- budget or rate (if shown)
- posted time
- required skills
- direct URL
STRICT RULES:
- Do NOT click any listing
- Read only what is visible in the listing cards
- Maximum 8 listings then stop
- If no results found, return {found: false}
Return JSON array: [{title, client, description, budget, posted, skills: [], url}]" \
--sync > /tmp/fg_contra.json &
# Agent 3 — We Work Remotely
tinyfish agent run \
--url "https://weworkremotely.com/remote-jobs/search?term={SKILL_ENCODED}" \
"You are on We Work Remotely job search results for '{SKILL}'.
Extract the first 8 visible job listings.
For each listing extract:
- title
- company name
- category (e.g. Front-End, Back-End, Design, etc.)
- posted date
- direct URL to the listing
STRICT RULES:
- Do NOT click any listing
- Read only what is visible in the search results
- Maximum 8 listings then stop
- If no results, return {found: false}
Return JSON array: [{title, company, category, posted, url}]" \
--sync > /tmp/fg_wwr.json &
# Agent 4 — Freelancer.com
tinyfish agent run \
--url "https://www.freelancer.com/jobs/?keyword={SKILL_ENCODED}" \
"You are on Freelancer.com job listings for '{SKILL}'.
Extract the first 8 visible job listings.
For each listing extract:
- title
- budget range (fixed or hourly)
- number of bids (if shown)
- posted time
- required skills listed
- direct URL
STRICT RULES:
- Do NOT click any listing
- Read only what is visible in the listing cards
- Maximum 8 listings then stop
Return JSON array: [{title, budget, bids, posted, skills: [], url}]" \
--sync > /tmp/fg_freelancer.json &
# Agent 5 — LinkedIn (contract/freelance filter)
tinyfish agent run \
--url "https://www.linkedin.com/jobs/search/?keywords={SKILL_ENCODED}&f_JT=C%2CF&f_WT=2&sortBy=DD" \
"You are on LinkedIn job search results for '{SKILL}' filtered to Contract and Freelance jobs, remote, sorted by most recent.
Extract the first 8 visible job listings.
For each listing extract:
- title
- company name
- location or remote status
- posted time
- salary or rate if shown
- direct URL
STRICT RULES:
- Do NOT click any listing
- Read only what is visible in the job cards
- Maximum 8 listings then stop
Return JSON array: [{title, company, location, posted, salary, url}]" \
--sync > /tmp/fg_linkedin.json &
wait
echo "=== UPWORK ===" && cat /tmp/fg_upwork.json
echo "=== CONTRA ===" && cat /tmp/fg_contra.json
echo "=== WWR ===" && cat /tmp/fg_wwr.json
echo "=== FREELANCER ===" && cat /tmp/fg_freelancer.json
echo "=== LINKEDIN ===" && cat /tmp/fg_linkedin.json
Before running, replace:
{SKILL}— e.g.React developer{SKILL_ENCODED}— URL-encoded e.g.React%20developer
Step 3 — Filter and present
From all results, deduplicate any listings that appear on multiple platforms and filter to only show listings posted within the last 7 days. Sort by recency — newest first.
## Freelance Gigs — {SKILL}
*Scraped live from Upwork · Contra · We Work Remotely · Freelancer · LinkedIn*
*{N} listings found · Posted in the last 7 days · {date}*
---
### 🔥 Fresh Listings
#### {Title}
**Platform:** {platform} · **Posted:** {posted}
**Budget:** {budget or rate}
**Skills:** {skills}
{description snippet}
🔗 {url}
---
#### {Title}
[same structure]
---
[up to 15 listings total, sorted by most recent]
---
### 📊 Quick Summary
| Platform | Listings Found | Avg Budget |
|---|---|---|
| Upwork | {n} | {avg} |
| Contra | {n} | - |
| We Work Remotely | {n} | - |
| Freelancer | {n} | {avg} |
| LinkedIn | {n} | {avg} |
---
### 💡 Tips for These Listings
{1-2 sentences of context — e.g. "Upwork has the most volume but high competition. Contra listings tend to be higher quality clients at better rates. LinkedIn contract roles are typically longer engagements."}
Edge Cases
- Upwork requires login to view listings — extract whatever is visible before the gate, note the limitation
- No listings found for skill — try alternative phrasings (e.g. "React" → "React.js", "frontend developer"; "Python" → "Python developer", "Django")
- Very niche skill — We Work Remotely and LinkedIn may have the richest results; Upwork/Freelancer tend to have more volume for common skills
- User wants a specific budget range — add budget filters to Upwork and Freelancer URLs before running
- User is in a specific country — note that Upwork and Freelancer are global but some listings are location-restricted; LinkedIn can be filtered by country
- All platforms return few results — suggest the user check back in a few days or broaden the skill (e.g. "React" instead of "React Native")