Chrome extension that tailors Vidya Sagar's LaTeX resume to any job posting.
All LLM traffic is routed through a local opencode serve instance and runs
inside one persistent opencode session - the session id is never rotated
unless you explicitly click "New session".
Chrome extension opencode serve (localhost:4096)
───────────────── ──────────────────────────────
jobScrapper.ts ──▶ extract JD ──▶ POST /session/<id>/message
background ──▶ tailor + cover ─▶ resume-tailor agent
──▶ match score ─▶ xelatex + cat heredoc
─▶ writes ~/Documents/Tailored-Resumes/
<Company>-<Role>/
vidya_sagar_resume.{tex,pdf}
Every request the extension sends - JD extraction, resume tailoring, cover
letter, match score, knowledge-file reads - uses the same opencode session
id stored in chrome.storage.local[opencodeSessionId]. This lets you watch
the full conversation in the opencode TUI in parallel.
# Sign in to GitHub Copilot if you haven't already.
opencode auth login # pick "GitHub Copilot"The resume-tailor agent was created at
~/.config/opencode/agent/resume-tailor.md. It is locked to:
- model:
github-copilot/claude-sonnet-4.6 - read:
~/Documents/Tailored-Resumes/**,~/vidya_sagar_resume.tex - bash:
mkdir,cat > *.tex|md|json,xelatex * - everything else: denied
OPENCODE_SERVER_PASSWORD=your-password \
opencode serve --hostname 127.0.0.1 --port 4096 \
--cors 'chrome-extension://*'Leave this running. The extension will reach it over HTTP basic auth.
pnpm install
pnpm buildIn Chrome:
chrome://extensions→ enable Developer mode- Load unpacked → select
build/chrome-mv3-prod
Open the options page (right-click the toolbar icon → Options) and:
- Connection tab → fill in URL + password → click Test connection
- Once green → click Refresh models → pick the tailor + extract models
- Click New session → this is the persistent session id used forever after
- Profile tab → click Open importer → paste
~/vidya_sagar_resume.tex - Knowledge tab → click Load contents → confirm both knowledge files exist (edit them in your editor when you want to update bio / latest work)
- Browse to a job posting (LinkedIn, Indeed, Greenhouse, Lever, Workday, Wellfound, Naukri, Glassdoor, or any page).
- Click the toolbar icon → Tailor resume for this page (or right-click → Tailor resume for this job).
- Review the extracted company / role / JD in the dialog.
- Click Tailor & compile resume.
- PDF lands at
~/Documents/Tailored-Resumes/<Company>-<Role>/vidya_sagar_resume.pdf.
The agent reads these on every run; edit them as your career progresses:
~/Documents/Tailored-Resumes/
├── _knowledge/
│ ├── about-me.md # bio + tone (used for Summary section)
│ └── latest-updates.md # recent achievements (newest at the top)
├── _template/
│ └── preamble.tex # your resume.tex as the canonical template
└── <Company>-<Role>/ # one folder per tailored resume
├── vidya_sagar_resume.tex
├── vidya_sagar_resume.pdf
├── cover_letter.md
└── match_score.json
Open the options page → Connection tab → Persistent session card:
- New session - POST /session, save the new id as active
- Verify - confirm the active id still exists on the server
- Clear - drop the active id (next request will fail until you set one)
- Paste a session id from
opencode session list→ Use this id to adopt an existing session (e.g. one you started in the TUI)
Session history (last 20) is kept so you can switch back at any time.
src/
├── api/
│ ├── opencodeClient.ts # HTTP client, persistent session enforcer
│ └── tailorService.ts # prompt assembly + result parsing
├── background/
│ ├── index.ts # service worker, context menu
│ ├── context-menu.ts # right-click → extract → open dialog
│ └── messages/
│ ├── generateDocuments.ts # main tailor pipeline
│ ├── opencodeSession.ts # create / verify / set session
│ ├── listProviders.ts # GET /config/providers
│ ├── testOpencodeConnection.ts
│ └── knowledgeFiles.ts # read about-me + latest-updates
├── components/ # profile editors (personal info, projects,
│ # experience, skills, education, certs,
│ # languages, tabs, array input, date picker)
├── contents/
│ └── jobScrapper.ts # JSON-LD → CSS selectors per board
├── storage/
│ └── keys.ts # canonical storage key set
├── tabs/
│ └── dialog.tsx # the tailoring dialog window
├── types/
│ ├── config.ts # LLMTuning + CustomPrompts
│ ├── opencode.ts # OpencodeConfig + SessionRef + defaults
│ └── userProfile.ts # UserProfile schema
├── popup.tsx
└── options.tsx