Skip to content
demonking-mwPublic

About

Computer-use job applier: an experimental workflow using a computer use model to fully autonomously acquire, filter, and apply for jobs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CUJA — Careers-Under-Jurisdiction Assistant

CUJA discovers relevant jobs, tracks them in a local queue, and fills application forms in a visible Chrome window. It always stops before Submit, leaving the final review and submission to you.

CUJA dashboard showing job queue status and suggested next steps CUJA has two interfaces:

  • Web UI (recommended): chat-driven discovery, queue management, application filling, status cards, schedules, and configuration.
  • CLI: direct commands for scripting discovery and application runs.

Quick start

1. Install prerequisites

CUJA supports Linux and WSL. Install:

  • Python 3.11 or newer, including the venv module
  • Node.js 18 or newer and npm
  • Git and curl
  • Google Chrome or Chromium for visible application filling
  • Azure CLI with access to Microsoft TRAPI, or a running copilot-api proxy

Application filling also requires a running ResuMix server. Discovery, queue management, and status views do not.

2. Clone and set up

git clone https://github.com/demonking-mw/cuja.git
cd cuja
./setup.sh

setup.sh is safe to re-run. It:

  1. Checks the required tool versions.
  2. Clones the agent framework to ../prototyper when it is not already there.
  3. Creates venv/ and installs the Python and Playwright dependencies.
  4. Installs the frontend dependencies with npm ci.
  5. Creates the ignored profile.yaml from profile.example.yaml.

To use an existing Prototyper checkout in another location:

CUJA_PROTOTYPER_DIR=/path/to/prototyper ./setup.sh

3. Add your profile and model login

Replace the example values in profile.yaml, especially personal, legal, education, screening_answers, and job_preferences. This file is ignored by Git and should never be committed.

The default model backend is Microsoft TRAPI:

az login

Alternatively, start a GitHub Copilot proxy in a separate terminal:

npx copilot-api@latest start \
  --account-type enterprise \
  --port 4141 \
  --rate-limit 6 \
  --wait

Then create config.local.yaml:

copilot_api:
  enabled: true

Local configuration is deep-merged over config.yaml and is ignored by Git.

4. Launch CUJA

From the repository root, run:

./run_ui.sh

Wait for both Backend ready. and the Vite ready message, then open:

http://localhost:3000

Keep that terminal running. Press Ctrl-C once to stop both servers.

If port 8000 or 3000 is occupied, choose free ports in the same command:

CUJA_BACKEND_PORT=18000 CUJA_FRONTEND_PORT=13000 ./run_ui.sh

Open the frontend URL printed by the launcher. Its API proxy automatically uses the selected backend port.

Enable application filling

ResuMix

Run ResuMix according to its setup guide; CUJA expects its API at http://localhost:5001. Add the local ResuMix user ID to config.local.yaml:

resumix:
  uid: "your-resumix-user-id"

Provide the password only at runtime:

export CUJA_RESUMIX_PWD='your-local-resumix-password'

If the variable is absent, CLI runs prompt for it. CUJA never stores the password in its configuration.

Chrome

With browser.auto_launch: true (the default), CUJA opens a visible Chrome window when an application run starts. The default profile at /tmp/cuja-chrome-profile has no saved logins.

For a persistent dedicated profile, add this to config.local.yaml:

browser:
  user_data_dir: "/home/you/.cuja-chrome"

You can instead launch Chrome yourself and let CUJA attach to it:

google-chrome \
  --remote-debugging-port=9222 \
  --user-data-dir="$HOME/.cuja-chrome"

Set browser.auto_launch: false when a manually started browser should be required. Sign in to job sites in that dedicated window before filling forms.

Using the web UI

  • Type a request such as Find five entry-level backend roles posted this week.
  • Use Discovery to search from the preferences in profile.yaml.
  • Use Status to inspect the queue and Apply All to fill queued jobs.
  • Watch progress cards and handle items marked needs_user.
  • Review every filled browser tab and its artifacts/<job_id>/diff_card.txt, then submit manually.

The UI persists conversations and job state in data/jobs.db.

CLI usage

Run these commands from the repository root with ./venv/bin/python:

# Discover and inspect
./venv/bin/python discover.py --search
./venv/bin/python discover.py --explore "https://boards.greenhouse.io/stripe" \
  --prompt "the five most recent backend roles"
./venv/bin/python discover.py --add "https://example.com/jobs/123"
./venv/bin/python discover.py --status

# Fill queued applications
./venv/bin/python apply.py --count 5
./venv/bin/python apply.py --ids 12,15,23
./venv/bin/python apply.py --retry-errors

# Extract and queue links from pasted text
printf '%s\n' "https://example.com/jobs/123" | \
  ./venv/bin/python paste_links.py

# Teach CUJA from corrections (finish input with Ctrl-D)
./venv/bin/python learn.py

Both interfaces share data/jobs.db, profile.yaml, and the same configuration.

Configuration

Committed defaults live in config.yaml. Put machine-specific values and overrides in the ignored config.local.yaml:

resumix:
  uid: "your-resumix-user-id"

browser:
  user_data_dir: "/home/you/.cuja-chrome"

copilot_api:
  enabled: false

Important settings:

Section Setting Purpose
resumix base_url, uid Resume-tailoring API and local user
browser cdp_endpoint, auto_launch, user_data_dir Visible Chrome connection
models role-specific deployment IDs Models used for planning and extraction
answer_engine match_threshold Screening-answer similarity threshold
orchestrator max_concurrent_tabs Maximum simultaneous application tabs

Troubleshooting

base_claude or ai_switch cannot be imported

Re-run ./setup.sh. If Prototyper lives elsewhere, use CUJA_PROTOTYPER_DIR=/path/to/prototyper for both setup and launch.

Port 8000 or 3000 is already in use

Stop the existing process, or launch with CUJA_BACKEND_PORT and CUJA_FRONTEND_PORT as shown above. The launcher exits instead of attaching to an unknown process.

The UI opens but model requests fail

For TRAPI, run az login and confirm your account has endpoint access. For Copilot, confirm http://localhost:4141 is reachable and copilot_api.enabled: true is present in config.local.yaml.

Application filling reports a failed preflight

Confirm Chrome CDP responds at http://localhost:9222/json/version, ResuMix responds at http://localhost:5001/health, and resumix.uid is configured.

Chrome opens without your logins

The default profile is intentionally disposable. Configure a dedicated browser.user_data_dir, open it once, and sign in before an application run.

How it works

Web UI / CLI
    |
    +-- discovery -> web search -> fit scoring -> data/jobs.db
    |
    `-- apply -> visible Chrome (CDP) -> page classification -> JD extraction
                 -> ResuMix tailoring -> field mapping -> ATS adapter / vision
                 -> diff card -> review in open browser tab
  • Greenhouse uses a DOM-first adapter.
  • Workday and unknown career sites can use the computer-use planner.
  • The answer engine matches screening questions to profile answers with local embeddings and escalates sensitive or uncertain fields.
  • Generated screenshots, tailored resumes, and diff cards stay under the ignored artifacts/ directory.

Project layout

apply.py, discover.py     CLI entry points
setup.sh, run_ui.sh       one-time setup and web UI launcher
config.yaml               committed defaults
profile.example.yaml      safe profile template
src/                      discovery, browser, ATS, answer, and orchestration code
ui/backend/               FastAPI, SSE, agent tools, scheduler, persistence
ui/frontend/              React and Vite interface
prompts/                  model prompt templates
data/                     local SQLite state (ignored)
artifacts/                per-job evidence and diff cards (ignored)

Safety and data

  • Never submits: CUJA fills forms and stops before submission.
  • Human review required: always verify every field and attachment.
  • No credential entry: login walls and captchas are left for you.
  • Local secrets stay ignored: .env, profile.yaml, config.local.yaml, data/, logs/, and artifacts/ are not committed.
  • Job pages are untrusted: page content is treated as data and framed against prompt injection.
  • External processing: profile, resume, job, and form context may be sent to the model endpoints configured in config.yaml; review those services' data policies before use.

About

Computer-use job applier: an experimental workflow using a computer use model to fully autonomously acquire, filter, and apply for jobs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages