ワンクリックで
upwork-proposal
Write a short, targeted Upwork proposal from a job description and the user's resume, humanized for natural tone.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Write a short, targeted Upwork proposal from a job description and the user's resume, humanized for natural tone.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Apply to a single job (URL or pasted page) with fit review, or drain the pending queue when no argument is given.
Search a job board and autonomously apply to matching jobs one at a time, until paused, exhausted, or the max-applications cap is hit.
Write a tailored one-page cover letter from a job description and the user's resume, humanized for natural tone.
Parse a resume's uploaded PDF into structured JSON (basics, experience, projects, skills, education) and save it to the editor.
Fetch the latest verification code or magic link from the connected mailbox for a given board domain. Called by apply / auto-apply for 2FA and account-creation flows.
Remove signs of AI-generated writing from text. Use when editing or reviewing text to make it sound more natural and human-written. Based on Wikipedia's comprehensive "Signs of AI writing" guide. Detects and fixes patterns including: inflated symbolism, promotional language, superficial -ing analyses, vague attributions, em dash overuse, rule of three, AI vocabulary words, negative parallelisms, and excessive conjunctive phrases.
| name | upwork-proposal |
| description | Write a short, targeted Upwork proposal from a job description and the user's resume, humanized for natural tone. |
| argument-hint | <proposal_id | job_description> |
Write a concise, winning Upwork proposal that directly addresses the client's needs. Clients skim proposals on mobile, between meetings - if it takes more than ~30 seconds to read, it's gone. Optimize every line for a fast skim.
Follow ../../shared/setup.md. Then Read the resume at primaryResumeSourceAbsolutePath for full context (identity, skills, experience, projects, research).
The argument is either a proposal id (an integer, when launched from the JobPilot UI) or a raw job description (manual use). Detect which:
Integer id → fetch the draft row and use its stored job details as the JD:
curl -fsS -H "authorization: Bearer $JOBPILOT_API_TOKEN" "$JOBPILOT_API/api/upwork/proposals/$ARG"
Use jobDescription as the posting, plus jobTitle / clientName / jobUrl for context. Remember the id - you will PATCH the result back to it in Step 7. (A draft launched from an Upwork search recommendation already has these fields filled and source:"search" - same flow, no extra work.)
Anything else → treat the argument itself as the job description. There is no row yet; you will POST a new one in Step 7.
Identify: what the client needs built/fixed, required tech and skills, scope and timeline clues, pain points/challenges, and any specific questions the client asks. Pull out one concrete detail unique to this posting - you'll reference it in the hook so the client can tell the proposal isn't a mass send.
Pick the SINGLE most relevant project from the resume - one that matches their problem, not just their tech stack. One specific, on-point case study beats five generic ones. Don't list everything. If a portfolio/GitHub/live link exists for it, keep that link ready.
Order it the way it gets read - them first, you second, never the reverse.
Hook (line 1, bolded): Open with a bold line that names their problem or goal in their words. Upwork renders **text** as bold - use it on this line so it stands out instantly. This is the single most important line; if it reads like "Hello, I'm excited to apply," the proposal is deleted. No "Hi" / "Dear client" / "I'm excited to apply" / "I came across your posting."
Case study (1–2 lines): One relevant project, stated specifically - what you built, the outcome with a real metric (users, perf gain, revenue), and a link if available. Tie it directly to what they need. Don't narrate your career; the client cares about their problem, not your journey.
Specific question (1 line): Ask ONE sharp question about their project that proves you read the posting and thought about it (scope, an edge case, a decision they'll need to make). This both shows engagement and opens a conversation.
CTA (1 line): End with a real next step - the specific question above, or a calendar link if the resume/profile provides one. Never end with a dead phrase like "Looking forward to hearing from you." Create the next step.
If the posting has screening questions, answer each one short, direct, and specific. "How many years with React?" → "4 years, including [project]." Never write a 300-word essay for a one-line question - long answers read as AI padding.
Invoke the humanizer skill on the full text.
Save the result so it appears on the Upwork page. screeningAnswers is a JSON array of { "question", "answer" } objects (empty [] if the posting had none).
Launched with an id → PATCH the existing draft (status stays draft):
curl -fsS -H "authorization: Bearer $JOBPILOT_API_TOKEN" -X PATCH "$JOBPILOT_API/api/upwork/proposals/$ARG" \
-H 'content-type: application/json' \
-d '{ "proposalText": "...", "screeningAnswers": [] }'
Launched with a raw job description → POST a new row:
curl -fsS -H "authorization: Bearer $JOBPILOT_API_TOKEN" -X POST "$JOBPILOT_API/api/upwork/proposals" \
-H 'content-type: application/json' \
-d '{ "jobTitle": "...", "clientName": "...", "jobUrl": "...", "jobDescription": "...", "proposalText": "...", "screeningAnswers": [] }'
jobTitle is required; derive it from the posting. Include clientName / jobUrl when the posting provides them.
Then print the proposal (and any screening answers, each labeled with its question) to the terminal so the user can paste it into Upwork.
Plain text proposal that pastes into Upwork's input. Use **bold** only on the line-1 hook (and sparingly on one key phrase if it genuinely helps a skim) - no markdown headers, no bullet lists in the body. Output screening-question answers separately, each labeled with its question.