The Problem
Job‑searchers spend hours maintaining spreadsheets, copying CVs, and manually scoring offers. The lack of a single source of truth makes it easy to miss deadlines, duplicate applications, or overlook high‑value opportunities.
What This Does
career‑ops stitches Claude Code agents, Playwright‑driven scraping, and a terminal UI into a unified pipeline. The Go entry point dashboard/main.go launches a TUI that lists applications, filters, and sorts them. Core data handling lives in dashboard/internal/data/career.go (parsing JSON job data, loading batch inputs, normalising company names). UI rendering and interaction are in dashboard/internal/ui/screens/*.go, with the most complex screen in pipeline.go (713 lines, 30 functions). PDF generation and theme handling are in the templates/ and dashboard/internal/theme/ packages.
How It Is Wired
Execution starts at func main() in dashboard/main.go (line 118). main calls Init, Update, and View, which together reach 15‑30 functions each.
Update→LoadReportSummary→cleanTableCell(filesystem read viaos.ReadFile).View→renderHeader→Width(called from nine places, the widest internal hub).
The data path begins with ParseApplications in career.go, which reads the applications file, then feeds structures to the UI screens. UI screens call helper functions such as NormalizeStatus (used by eight callers) and applyFilterAndSort (used by three callers). The most‑impactful functions—Width, NormalizeStatus, CurrentApp—are invoked from multiple locations, so changes there propagate broadly. No circular imports were detected; the import graph consists of ten isolated internal modules.
File responsibilities (ranked by call‑graph reach):
| File | Core duties | Reach |
|---|---|---|
pipeline.go | Defines NewPipelineModel, UI layout, resize, width/height calculations | 30 functions, 8 types |
career.go | Parses applications, loads batch URLs, normalises company data, reads files | 13 functions, 3 types |
viewer.go | Viewer model, init, resize, update, body height (reads files) | 10 functions, 2 types |
theme.go / catppuccin.go | Theme construction (NewTheme) | 2 functions |
main.go | TUI bootstrap (Init, Update, View) | 4 functions |
All external effects are file reads (os.ReadFile) performed in ParseApplications and LoadReportSummary. No network calls are visible in the static analysis; the Playwright agents are invoked from the Claude Code side, not from the Go code.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/career-ops
cd career-ops
# Install Node dependencies (Playwright for PDF generation)
npm install
npx playwright install chromium
# Validate the environment
npm run doctor # defined in package.json, checks Go, Playwright, etc.
# Configure your profile (required fields in config/profile.yml)
cp config/profile.example.yml config/profile.yml
# Edit config/profile.yml with your CV, preferences, API keys, etc.
# Run the terminal UI
go run ./dashboard/main.go
The UI lets you press a to add a URL, e to evaluate, p to generate a PDF, and arrow keys to navigate. Batch mode can be driven via the .opencode/commands/ scripts (e.g., career-ops-batch) which ultimately invoke the same Go functions.
Real‑World Use
A hiring engineer can point the UI at a list of Greenhouse URLs, let Claude evaluate each against a stored CV, and export a tailored PDF for any offer scoring above 4.0/5. The generated PDF and the normalized status are then committed to the local reports/ folder, providing an audit trail that can be version‑controlled alongside source code.
Code Health & Issues
- High – No test suite – 17 source files, 0 test files. Add unit tests for each public entry point and gate them with CI.
- High – Missing lockfile –
package.jsonpresent withoutpackage-lock.json/yarn.lock. Runnpm installand commit the generated lockfile. - High – No CI workflow – No GitHub Actions or other CI config. Add a workflow that runs
go buildandnpm test. - Medium – Dependabot disabled – No
.github/dependabot.yml. Add one covering Go, Node, and GitHub Actions. - Medium – Large binary in repo –
docs/demo.gif(8.3 MiB). Move to Git LFS or external storage. - Medium – Deep nesting –
career.goandviewer.gohave indentation depth 6, making control flow hard to follow. Refactor with early returns or helper functions. - Medium – Duplicated code – Repeated 6‑line blocks across several UI screens and JS helpers. Extract shared helpers.
- Medium – Oversized file –
pipeline.gocontains 713 lines; split by responsibility (e.g., layout vs. data handling). - Medium – High branching density – 171 branch points across 487 lines in several files; consider strategy tables or polymorphic dispatch.
The Bottom Line
career‑ops delivers a functional, AI‑augmented job‑search workflow with a usable TUI and PDF output, but the codebase suffers from maintainability issues (large files, duplicated logic) and a weak production pipeline (no tests, CI, or lockfile). It is suitable for teams comfortable extending Go/Node code and willing to invest in test and CI scaffolding.