--- name: freelance-gig-finder description: Find fresh freelance and contract opportunities across multiple platforms for any skill set. Use this skill when a user asks "find me freelance React jobs", "Upwork gigs for Python developers", "freelance work posted this week", "contract jobs for designers", "find me remote freelance opportunities for [skill]", "I'm looking for freelance work", "what freelance gigs are available for [skill]", or any request to find paid freelance or contract work online. --- # Freelance 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?** ```bash 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?** ```bash 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. ```bash # 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")