Skip to content

creativereason/deckhandAI

Repository files navigation

deckhandAI

A self-hosted job search command center. Track prospects, scrape target company career pages, and generate ATS-safe resumes and cover letters with any AI model — no vendor lock-in, no database, no monthly fee.

→ Product overview — features, screenshots, and context on why it exists.

→ View live demo — interactive, no login required. It's a shared board seeded with sample data that resets nightly; scraping is disabled, everything else works.


What it does

  • Personal job tracker — manage everything from first look to final decision; track prospects you're watching, applications in flight, and roles you've passed on, all in one private board
  • Automated scraping — Playwright-based scraper hits target career pages on a schedule via GitHub Actions
  • AI throughout — chat assistant, job fit scoring, ATS-safe resume tailoring, and cover letter generation; bring your own model (Anthropic, OpenAI, Ollama, or any OpenAI-compatible endpoint)
  • Zero infrastructure — data lives in flat JSON files in your own private GitHub repo; deploy the UI to Vercel for free

Screenshots

Job tracker board, filtered to strong-fit prospects

Prospects filtered to strong-fit roles — one board for everything from first look to final decision.

Job detail page
Job detail
AI chat assistant
AI chat assistant
Onboarding wizard
Onboarding wizard

Quick start

# 1. Clone and install
git clone https://github.com/creativereason/deckhandAI.git
cd deckhandAI
pnpm install

# 2. Run the setup wizard
node scripts/setup.mjs
# Prompts for GitHub token, data repo, app password, candidate profile,
# and AI provider — then writes .env.local, data/config.json, and data/profile.json

# 3. Run locally
pnpm dev   # http://localhost:3000

Want sample data to start from? Run the data repo init script:

node scripts/init-sample-repo.mjs
# Creates a GitHub repo pre-populated with a realistic fictional candidate profile,
# job tracker data, work history, and scrape targets.

Prefer to configure manually? Copy the sample files and edit them directly:

cp data/config.sample.json data/config.json
cp data/profile.sample.json data/profile.json
cp data/jobs.sample.json data/jobs.json

Deploy to Vercel

Deploy with Vercel

Set these environment variables in your Vercel project settings:

Variable Required Description
GITHUB_TOKEN Yes Personal access token with repo scope
GITHUB_DATA_REPO Yes username/repo-name of your private data repo
GITHUB_DATA_BRANCH No Branch to read/write (default: main)
APP_PASSWORD Yes Password to protect the tracker UI
COOKIE_SECRET Yes Random 32+ character string for signing session cookies
AI_API_KEY No API key for Anthropic, OpenAI, etc.
AI_PROVIDER No anthropic | openai | ollama | custom (default: anthropic)
AI_BASE_URL No Ollama or custom endpoint base URL
BRAVE_SEARCH_API_KEY No Brave Search API key. Used by the weekly job search script and, in "Evaluate a job," as a fallback to find a plain-fetchable cross-post when the given URL can't be fetched directly (e.g. Workday). Without it, that fallback is silently skipped.
DEMO_MODE No true to enable demo mode: bypasses auth, disables the scraper, and reads/writes GITHUB_DATA_REPO (point it at a public sample-data repo)
NEXT_PUBLIC_DEMO_MODE No true to show the demo-mode banner in the UI

The setup wizard generates these values for you locally. For Vercel, copy the values from your .env.local into your project's environment variable settings.


Sample data repo

The quickest way to get a data repo with realistic starter data:

node scripts/init-sample-repo.mjs

This creates a new GitHub repo under your account and uploads pre-filled jobs.json, config.json, profile.json, and scrape-targets.json based on a fictional candidate (Alex Chen, Director of Product Design in Austin, TX). Use it as a starting point — swap in your own details in Settings after first login.

The same sample files power the live demo.

To host your own demo deployment:

  1. Run init-sample-repo.mjs with a public repo
  2. Deploy deckhandAI to Vercel with:
    GITHUB_DATA_REPO=yourhandle/deckhandai-sample-data
    DEMO_MODE=true
    NEXT_PUBLIC_DEMO_MODE=true
    
    No APP_PASSWORD needed — demo mode bypasses auth. Visitors can add/edit/move jobs and use AI generation; the scraper stays disabled since it launches a real headless browser against live career pages.
  3. Add repo secrets DEMO_DATA_REPO (yourhandle/deckhandai-sample-data) and DEMO_DATA_REPO_TOKEN (a token with write access to it), then enable the Reset demo data GitHub Actions workflow. It runs nightly and overwrites the demo repo's data files back to data/*.sample.json, so a public, unauthenticated demo doesn't drift or fill up with junk. Trigger it manually any time via workflow_dispatch if you want an immediate reset.
  4. Consider using separate, low-limit keys for the demo deployment's AI_API_KEY and BRAVE_SEARCH_API_KEY — both are reachable by anonymous visitors. Brave's free tier caps at 2,000 queries/month, which is plenty to bound the blast radius for a demo.

Configuration

data/config.json controls your candidate profile, job filter preferences, and AI settings. The setup wizard writes this file for you, or copy from data/config.sample.json and edit manually.

Key fields:

  • candidate — name, email, phone, website, LinkedIn
  • preferences.titles — target job titles used for scrape filtering
  • preferences.salary — minimum FTE base and contract hourly rate
  • preferences.locations — remote/hybrid flags, hub city, hybrid radius in miles
  • ai — provider, model, and optional base URL

Profile (for AI generation)

data/profile.json is your structured work history — the source material the AI uses to write cover letters and resume tailoring notes. The setup wizard creates an initial version; edit it directly to add your experience bullets, strengths, and writing style rules.

See data/profile.sample.json for the full schema.


Scraping

Add and manage scrape targets in two ways:

  • Settings UI — go to Settings → Scrape Sources to add, edit, or remove targets without touching any files. Changes are saved to data/scrape-targets.json in your data repo.
  • Script — edit scripts/scrape-careers.mjs directly for bulk setup or to define custom selectors. The script reads from data/scrape-targets.json at runtime if it exists, falling back to the targets defined in the file.

On-demand scrape from the UI: ask the Deckhand chat assistant to "scrape for new jobs" — it runs your configured remote and local targets and streams per-target progress into the chat. Scheduled runs (below) remain the primary path for hands-off scraping; the chat prompt is for a manual run without leaving the board.

Run the scraper manually or let GitHub Actions run it on a schedule:

node scripts/scrape-careers.mjs

Requires Playwright with Chromium:

npx playwright install chromium

Vercel deployments cannot run the scraper. Vercel's serverless environment does not support Chromium. To use automated scraping, run the scraper from your own machine or a self-hosted server — either on a schedule via cron or via the GitHub Actions workflow (.github/workflows/scrape.yml), which runs the script in a standard Ubuntu runner that supports Playwright.

Scheduling your own runs? .github/workflows/scrape.yml in this repo is a template — never add your own secrets to the shared upstream repo. See docs/scheduled-scraping.md for hosting it in your own fork or (recommended) directly in your private data repo.


Scheduled job searching

Beyond scraping your target companies, deckhandAI can search job boards automatically and populate the pending queue without any manual effort. Three approaches are supported — GitHub Actions, system cron, and Claude Code's built-in scheduler — depending on how you run the app.

docs/scheduled-job-search.md


AI features

deckhandAI uses AI throughout the workflow — not just for document output. All features run through the same provider you configure, so one API key covers everything.

Chat assistant ("Your Deckhand") An always-visible panel on the board — stacked above the tracker on mobile, a sticky rail alongside it on larger screens — plus a per-job chat on the job detail page. Ask questions about your pipeline, evaluate a job URL, scan for ghost jobs, trigger an on-demand scrape of your configured career-page targets, or have it add, move, or update jobs through natural language.

Job fit evaluation Each job in your tracker can be scored against your target titles, salary floor, and location preferences. The AI explains why a role is a strong fit or a caution, surfacing signal you'd otherwise have to read manually.

At-a-glance role summaries Every job gets a 1–2 sentence AI summary of what the role is and what the company does — shown on the board card and in the job detail header, so you get the gist without re-reading notes or the full JD. Summaries are generated automatically when jobs are added; bring an existing board up to date once with pnpm backfill:summaries.

Cover letter generation Drafts a tailored cover letter from your work history (profile.json) and the job description. Streamed in real time, editable inline, and exportable as a styled DOCX or print-to-PDF.

ATS-safe resume tailoring Takes your base resume and rewrites the summary and experience bullets to match the specific role — single-column layout, no tables or text boxes, bullets via proper list markup so they survive every ATS parser. Outputs a ready-to-submit DOCX.

Provider options deckhandAI supports several AI providers. Choose whichever fits your setup.

Option 1 — Anthropic (Claude)

Requires an Anthropic Console account at console.anthropic.com. This is separate from a Claude.ai subscription — the API is pay-as-you-go with credits you add to your account. A standard Claude.ai plan does not include API access.

Cost in practice: generating a cover letter with claude-sonnet-4-6 costs a few cents per call. $5–10 in credits goes a long way for personal use.

{
  "ai": {
    "provider": "anthropic",
    "model": "claude-sonnet-4-6",
    "base_url": null
  }
}
AI_API_KEY=sk-ant-...

Option 2 — OpenAI

Requires an OpenAI account at platform.openai.com with credits loaded. Same pay-as-you-go model.

{
  "ai": {
    "provider": "openai",
    "model": "gpt-4o",
    "base_url": null
  }
}
AI_API_KEY=sk-...

Option 3 — Ollama (local, free)

If you have Ollama running on your machine or local network, you can use it with no API key and no per-call cost. Good models for this use case: llama3, mistral, phi3.

ollama pull llama3   # one-time download
ollama serve         # runs at http://localhost:11434
{
  "ai": {
    "provider": "ollama",
    "model": "llama3",
    "base_url": "http://localhost:11434/v1"
  }
}

No AI_API_KEY needed.

Option 4 — Gemini (Google, has a free tier)

Google Gemini has a free tier with generous rate limits — a good starting point if you don't want to add a credit card. Get an API key at aistudio.google.com (free, just needs a Google account).

{
  "ai": {
    "provider": "custom",
    "model": "gemini-2.0-flash",
    "base_url": "https://generativelanguage.googleapis.com/openai/v1"
  }
}
AI_API_KEY=your-google-ai-studio-key

gemini-2.0-flash is fast and capable for document generation. gemini-1.5-pro is stronger if quality matters more than speed.

Option 5 — Grok (xAI)

Grok is OpenAI-compatible and tends to have competitive pricing. Get an API key at console.x.ai.

{
  "ai": {
    "provider": "custom",
    "model": "grok-3",
    "base_url": "https://api.x.ai/v1"
  }
}
AI_API_KEY=your-xai-key

Option 6 — Other OpenAI-compatible endpoints

Any OpenAI-compatible API works the same way — LM Studio, vLLM, or any other local server. Set provider to custom, point base_url at your server, and set the model name to whatever your server expects.

{
  "ai": {
    "provider": "custom",
    "model": "your-model-name",
    "base_url": "http://your-server:port/v1"
  }
}

Set your provider via the setup wizard (node scripts/setup.mjs) or edit data/config.json directly. The API key goes in .env.local as AI_API_KEY.


Data privacy

jobs.json, config.json, and profile.json are gitignored by default. Your job search data, salary notes, application history, and work history never leave your own deployment. AI generation happens server-to-model — your data is not sent to any third party beyond the AI provider you configure.


What's next

See ROADMAP.md for planned features including an AI chat assistant, ghost job detection, and more.


Contributing

See CONTRIBUTING.md.


License

MIT

About

▎ A personal job search command center you can deploy in minutes. Track prospects, scrape target companies, and generate cover letters with any AI model — no vendor lock-in, no database, no monthly fee.

Resources

License

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors