chameleon-cv 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. chameleon_cv-0.1.0/LICENSE +21 -0
  2. chameleon_cv-0.1.0/PKG-INFO +383 -0
  3. chameleon_cv-0.1.0/README.md +356 -0
  4. chameleon_cv-0.1.0/chameleon_cv.egg-info/PKG-INFO +383 -0
  5. chameleon_cv-0.1.0/chameleon_cv.egg-info/SOURCES.txt +64 -0
  6. chameleon_cv-0.1.0/chameleon_cv.egg-info/dependency_links.txt +1 -0
  7. chameleon_cv-0.1.0/chameleon_cv.egg-info/entry_points.txt +3 -0
  8. chameleon_cv-0.1.0/chameleon_cv.egg-info/requires.txt +5 -0
  9. chameleon_cv-0.1.0/chameleon_cv.egg-info/top_level.txt +1 -0
  10. chameleon_cv-0.1.0/pyproject.toml +44 -0
  11. chameleon_cv-0.1.0/scripts/__init__.py +1 -0
  12. chameleon_cv-0.1.0/scripts/__main_tui__.py +11 -0
  13. chameleon_cv-0.1.0/scripts/ats_ghost.py +170 -0
  14. chameleon_cv-0.1.0/scripts/cache.py +63 -0
  15. chameleon_cv-0.1.0/scripts/cli.py +109 -0
  16. chameleon_cv-0.1.0/scripts/config.py +376 -0
  17. chameleon_cv-0.1.0/scripts/cover_letter.py +105 -0
  18. chameleon_cv-0.1.0/scripts/db.py +331 -0
  19. chameleon_cv-0.1.0/scripts/fonts.py +186 -0
  20. chameleon_cv-0.1.0/scripts/ghost.py +88 -0
  21. chameleon_cv-0.1.0/scripts/job_matcher.py +636 -0
  22. chameleon_cv-0.1.0/scripts/job_scanner/__init__.py +8 -0
  23. chameleon_cv-0.1.0/scripts/job_scanner/__main__.py +6 -0
  24. chameleon_cv-0.1.0/scripts/job_scanner/base.py +197 -0
  25. chameleon_cv-0.1.0/scripts/job_scanner/browser.py +244 -0
  26. chameleon_cv-0.1.0/scripts/job_scanner/cli.py +6 -0
  27. chameleon_cv-0.1.0/scripts/job_scanner/parsers/__init__.py +24 -0
  28. chameleon_cv-0.1.0/scripts/job_scanner/parsers/adzuna.py +81 -0
  29. chameleon_cv-0.1.0/scripts/job_scanner/parsers/arc.py +65 -0
  30. chameleon_cv-0.1.0/scripts/job_scanner/parsers/crypto_careers.py +88 -0
  31. chameleon_cv-0.1.0/scripts/job_scanner/parsers/dailyremote.py +91 -0
  32. chameleon_cv-0.1.0/scripts/job_scanner/parsers/flexjobs.py +91 -0
  33. chameleon_cv-0.1.0/scripts/job_scanner/parsers/himalayas.py +47 -0
  34. chameleon_cv-0.1.0/scripts/job_scanner/parsers/hn_hiring.py +94 -0
  35. chameleon_cv-0.1.0/scripts/job_scanner/parsers/indeed.py +98 -0
  36. chameleon_cv-0.1.0/scripts/job_scanner/parsers/jobicy.py +60 -0
  37. chameleon_cv-0.1.0/scripts/job_scanner/parsers/jooble.py +68 -0
  38. chameleon_cv-0.1.0/scripts/job_scanner/parsers/linkedin.py +140 -0
  39. chameleon_cv-0.1.0/scripts/job_scanner/parsers/opentoworkremote.py +53 -0
  40. chameleon_cv-0.1.0/scripts/job_scanner/parsers/relocate.py +95 -0
  41. chameleon_cv-0.1.0/scripts/job_scanner/parsers/remote_rocketship.py +90 -0
  42. chameleon_cv-0.1.0/scripts/job_scanner/parsers/remoteok.py +63 -0
  43. chameleon_cv-0.1.0/scripts/job_scanner/parsers/remotive.py +57 -0
  44. chameleon_cv-0.1.0/scripts/job_scanner/parsers/web3_career.py +92 -0
  45. chameleon_cv-0.1.0/scripts/job_scanner/parsers/wellfound.py +94 -0
  46. chameleon_cv-0.1.0/scripts/job_scanner/parsers/weworkremotely.py +60 -0
  47. chameleon_cv-0.1.0/scripts/job_scanner/parsers/ycomb.py +83 -0
  48. chameleon_cv-0.1.0/scripts/job_scanner/registry.py +65 -0
  49. chameleon_cv-0.1.0/scripts/job_scanner/scanner.py +162 -0
  50. chameleon_cv-0.1.0/scripts/question.py +107 -0
  51. chameleon_cv-0.1.0/scripts/render.py +110 -0
  52. chameleon_cv-0.1.0/scripts/review.py +89 -0
  53. chameleon_cv-0.1.0/scripts/setup.py +139 -0
  54. chameleon_cv-0.1.0/scripts/tailor_brief.py +379 -0
  55. chameleon_cv-0.1.0/scripts/tailor_cv.py +746 -0
  56. chameleon_cv-0.1.0/scripts/tailor_prompts.py +101 -0
  57. chameleon_cv-0.1.0/scripts/tui/__init__.py +1 -0
  58. chameleon_cv-0.1.0/scripts/tui/app.py +1547 -0
  59. chameleon_cv-0.1.0/scripts/tui/helpers.py +65 -0
  60. chameleon_cv-0.1.0/scripts/tui/screens.py +642 -0
  61. chameleon_cv-0.1.0/scripts/tui/widgets.py +276 -0
  62. chameleon_cv-0.1.0/scripts/tui_app.py +25 -0
  63. chameleon_cv-0.1.0/scripts/wizard.py +109 -0
  64. chameleon_cv-0.1.0/setup.cfg +4 -0
  65. chameleon_cv-0.1.0/tests/test_job_matcher.py +143 -0
  66. chameleon_cv-0.1.0/tests/test_tailor_brief.py +78 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 David Alecrim
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,383 @@
1
+ Metadata-Version: 2.4
2
+ Name: chameleon-cv
3
+ Version: 0.1.0
4
+ Summary: AI-powered resume tailor — tailor your CV to any job posting with ATS-optimized PDFs
5
+ Author: chameleon
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/HautlyS/chameleon
8
+ Project-URL: Repository, https://github.com/HautlyS/chameleon
9
+ Keywords: resume,cv,tailor,ats,job-search,ai,rendercv
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Office/Business :: News/Diary
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: PyYAML>=6.0
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: pypdf>=4.0
24
+ Requires-Dist: reportlab>=4.0
25
+ Requires-Dist: textual>=1.0.0
26
+ Dynamic: license-file
27
+
28
+ # Chameleon — Resume Tailor
29
+
30
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)](https://python.org)
31
+ [![MIT License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
32
+ [![OpenCode](https://img.shields.io/badge/OpenCode-ready-blueviolet)](https://opencode.ai)
33
+ [![Claude Code](https://img.shields.io/badge/Claude%20Code-ready-darkviolet)](https://claude.ai)
34
+ [![Codex](https://img.shields.io/badge/Codex-ready-black)](https://openai.com/codex)
35
+
36
+ Tailor your master resume to any job posting with AI. Produces ATS-optimized PDFs without inventing experience. Works as a **TUI**, **CLI**, or via **AI assistant** (OpenCode / Claude Code / Codex).
37
+
38
+ ---
39
+
40
+ ## Why Chameleon?
41
+
42
+ | Problem | Chameleon |
43
+ |---------|-----------|
44
+ | Generic resume rejected by ATS | Tailored keywords + **invisible ATS injection** |
45
+ | Fabricated skills get caught | **Strict no-fabrication** rules enforced by AI and code |
46
+ | Lost track of applications | **Persistent analysis** — JSON artifacts saved for reuse |
47
+ | Manual tailoring takes hours | **4-pass pipeline** runs in under 2 minutes |
48
+ | No feedback loop | **Score every CV** against the JD with category breakdowns |
49
+ | Scattered job platforms | **20-platform scanner** with API, RSS, and scraping |
50
+
51
+ ---
52
+
53
+ ## Quick Start
54
+
55
+ ### Prerequisites
56
+
57
+ - Python 3.10+
58
+ - An AI assistant binary: [OpenCode](https://opencode.ai), [Claude Code](https://claude.ai/claude-code), or [Codex CLI](https://openai.com/codex)
59
+
60
+ ### Install
61
+
62
+ ```bash
63
+ git clone https://github.com/davidalecrim1/chameleon.git
64
+ cd chameleon
65
+ make install-tools # creates .venv + installs rendercv
66
+ ```
67
+
68
+ ### Makefile Targets
69
+
70
+ | Target | Usage | Description |
71
+ |--------|-------|-------------|
72
+ | `install-tools` | `make install-tools` | Create `.venv`, install `rendercv[full]` |
73
+ | `render` | `make render FILE=<yaml>` | Render a CV YAML to PDF |
74
+ | `tailor` | `make tailor JD=<text> COMPANY=<name>` | Tailor CV for a job posting |
75
+ | `score` | `make score JD=<text>` | Score job match against profile |
76
+ | `scan` | `make scan QUERY=<query>` | Scan job platforms |
77
+ | `scan-all` | `make scan-all` | Scan all 20 platforms |
78
+ | `scan-tier1` | `make scan-tier1` | Scan Tier 1 platforms only |
79
+ | `list-platforms` | `make list-platforms` | List available scanner platforms |
80
+
81
+ ---
82
+
83
+ ## Three Ways to Use
84
+
85
+ ### 1. TUI — Full Terminal UI
86
+
87
+ ```bash
88
+ ./tui.sh
89
+ ```
90
+
91
+ Browse scored jobs from 20 platforms, tailor with `Ctrl+T`, view diffs between master and tailored YAML, and edit config live — all in the terminal.
92
+
93
+ **6 Tabs:**
94
+
95
+ | Tab | Shortcut | Shows |
96
+ |-----|----------|-------|
97
+ | **Jobs** | `Ctrl+1` | Scanned/pasted jobs with scores, gap analysis, experience fit |
98
+ | **Editor** | `Ctrl+2` | Inline nano-style editor for job descriptions |
99
+ | **Profile** | `Ctrl+3` | GitHub profile (languages, tech stack, matching repos) |
100
+ | **Scanner** | `Ctrl+4` | Live pipeline logs — scan progress, tailor phases, render status |
101
+ | **Tailored** | `Ctrl+5` | Tailored CVs with diff view, scores, PDF links |
102
+ | **Settings** | `Ctrl+6` | Live config editor — paths, scan queries, score weights, fonts, colors |
103
+
104
+ **Keybindings:**
105
+
106
+ | Key | Action |
107
+ |-----|--------|
108
+ | `Ctrl+Q` | Quit (with confirmation) |
109
+ | `Ctrl+S` | Scan job platforms |
110
+ | `Ctrl+Shift+S` / `F2` | Custom scan with platform/query options |
111
+ | `Ctrl+N` | Paste a job description |
112
+ | `Ctrl+E` | Edit selected job description |
113
+ | `Ctrl+T` | Tailor CV for selected job |
114
+ | `Ctrl+R` | Re-score all jobs |
115
+ | `Ctrl+D` | Delete selected job |
116
+ | `Ctrl+O` | Open job URL in browser |
117
+ | `Enter` | Show job detail or tailored CV diff |
118
+ | `/` | Focus search bar |
119
+ | `F1` | Help screen |
120
+ | `F5` | Refresh / re-score |
121
+ | `↑/↓` | Navigate rows |
122
+
123
+ Full reference: [docs/TUI.md](docs/TUI.md)
124
+
125
+ ---
126
+
127
+ ### 2. AI Assistant — Slash Commands
128
+
129
+ ```bash
130
+ opencode # or claude, or codex
131
+ ```
132
+
133
+ | Command | What it does |
134
+ |---------|-------------|
135
+ | `/init-cv <path>` | Import master CV from PDF or YAML |
136
+ | `/chameleon <url-or-text>` | Full pipeline: analyze → tailor → render |
137
+ | `/tailor-cv --analysis <id> --cv <name>` | Tailor from saved analysis |
138
+ | `/score-cv --analysis <id> --cv <path>` | Score against analysis |
139
+ | `/cover-letter <url-or-text>` | Generate cover letter |
140
+ | `/question "<text>"` | Answer screening question |
141
+ | `/render-cv [file]` | Re-render a YAML to PDF |
142
+ | `/scan-jobs [--query]` | Scan job platforms |
143
+ | `/job-matcher score --job-url <url>` | Score job against your profile |
144
+
145
+ ---
146
+
147
+ ### 3. CLI — Headless / Scripting
148
+
149
+ ```bash
150
+ # ── Unified CLI (recommended) ──────────────────────────────────────────
151
+
152
+ # Tailor a CV from text
153
+ ./chameleon tailor "Senior Rust Engineer at Acme Corp..." --company Acme
154
+
155
+ # Tailor from a URL (auto-crawls the job posting)
156
+ ./chameleon tailor https://jobs.example.com/senior-rust-engineer
157
+
158
+ # Tailor from a file
159
+ ./chameleon tailor jd.txt --company Acme --title "Rust Engineer"
160
+
161
+ # Pipe a job description via stdin
162
+ cat jd.txt | ./chameleon tailor --company Acme
163
+
164
+ # Score a job match against your profile
165
+ ./chameleon score "Python developer, Django, PostgreSQL..."
166
+ ./chameleon score https://jobs.example.com/python-dev --json
167
+
168
+ # Scan job platforms
169
+ ./chameleon scan -q "rust engineer" --tier1
170
+ ./chameleon scan -q "python" -p remoteok,remotive --json
171
+ ./chameleon scan --all --limit 10 -o output/scans/results.json
172
+
173
+ # Render a YAML to PDF
174
+ ./chameleon render templates/david_acme_rust_engineer_cv.yaml
175
+
176
+ # ── Windows ─────────────────────────────────────────────────────────────
177
+ chameleon.bat tailor "Senior Rust Engineer..." --company Acme
178
+ chameleon.bat score "Python developer..."
179
+ chameleon.bat scan -q "rust engineer" --tier1
180
+
181
+ # ── Direct Python modules (alternative) ─────────────────────────────────
182
+
183
+ # Tailor a CV directly
184
+ python3 -m scripts.tailor_cv "Senior Rust Engineer at Acme..." --company Acme --title Engineer
185
+
186
+ # Score a job against your profile
187
+ python3 -m scripts.job_matcher "Python developer..." --json
188
+
189
+ # Scan job platforms
190
+ python3 -m scripts.job_scanner.scanner --query "rust engineer" --platforms remoteok,hn_hiring --json
191
+
192
+ # Render a YAML
193
+ make render FILE=templates/david_acme_rust_engineer_cv.yaml
194
+
195
+ # ── Make targets ────────────────────────────────────────────────────────
196
+
197
+ make tailor JD="Senior Rust Engineer..." COMPANY=Acme
198
+ make score JD="Python developer..."
199
+ make scan QUERY="rust engineer" PLATFORMS=remoteok,hn_hiring
200
+ make scan-all QUERY="python"
201
+ make scan-tier1
202
+ make list-platforms
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Example Workflow
208
+
209
+ ```bash
210
+ # 1. Import your master CV
211
+ /init-cv ~/Documents/resume.pdf
212
+ # → templates/david_cv.yaml
213
+
214
+ # 2. Tailor for a job posting
215
+ /chameleon https://jobs.example.com/senior-engineer-123
216
+ # → Analysis: output/job_analyses/a7c19f2d__Acme__Rust_Engineer.json
217
+ # → Tailored YAML: templates/david_acme_rust_engineer_cv.yaml
218
+ # → PDF: output/david_acme_rust_engineer_cv.pdf
219
+
220
+ # 3. Score the result against the same analysis
221
+ /score-cv --analysis a7c19f2d --cv templates/david_acme_rust_engineer_cv.yaml
222
+ # → Score: 85/100 (Languages: 22, Frameworks: 20, Domains: 23, CV Alignment: 20)
223
+ ```
224
+
225
+ ---
226
+
227
+ ## How It Works
228
+
229
+ ### 4-Pass Pipeline
230
+
231
+ When you invoke a tailor (`Ctrl+T` or `/chameleon`), the pipeline runs in 4 passes:
232
+
233
+ ```
234
+ Pass 1: TailoringBrief Algorithmic JD analysis — seniority, gaps, repo matching
235
+ Pass 2: AI Tailor LLM rewrites summary, reorders highlights/skills
236
+ Pass 3: AI Review Double review with tiebreaker, applies corrections
237
+ Pass 4: Render rendercv → PDF (+ optional ATS ghost injection)
238
+ ```
239
+
240
+ ### ATS Ghost Injection
241
+
242
+ When `ats_ghost_enabled` is on, the PDF is post-processed to inject invisible keyword text (`font-size: 1px, color: white`) at the bottom of every page. This ensures ATS parsers see important keywords even if the layout is unusual. Extra terms can be configured in Settings.
243
+
244
+ ---
245
+
246
+ ## Project Layout
247
+
248
+ ```
249
+ .chameleon/ Config JSON, SQLite DB, fonts, cache
250
+ .claude/ AI skills + agents (OpenCode / Claude Code)
251
+ .agents/ AI skills + agents (Codex)
252
+ opencode.json OpenCode project config (12 commands, permissions)
253
+ templates/ Master + tailored CV YAMLs
254
+ output/ Rendered PDFs, job analysis JSONs
255
+ profiles/ GitHub profile data
256
+ chameleon.sh CLI entry point (Unix/Mac)
257
+ chameleon.bat CLI entry point (Windows)
258
+ scan.sh / scan.bat Quick scanner wrapper
259
+ score.sh / score.bat Quick scorer wrapper
260
+ tui.sh / tui.bat TUI launcher
261
+ scripts/
262
+ tui/ Textual TUI (6 tabs, 19 keybindings)
263
+ job_scanner/ 20-platform job scanner
264
+ tailor_cv.py 4-pass pipeline entry point
265
+ tailor_brief.py Algorithmic JD analysis
266
+ tailor_prompts.py AI prompt templates
267
+ job_matcher.py Scoring engine (4-category rubric)
268
+ config.py JSON-backed configuration
269
+ db.py SQLite persistence
270
+ render.py RenderCV wrapper
271
+ ats_ghost.py Invisible ATS keyword injection
272
+ docs/
273
+ ARCHITECTURE.md Component architecture, data flow, config ref
274
+ TUI.md Full TUI keybinding and tab reference
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Configuration
280
+
281
+ All settings live in `.chameleon/config.json`. Editable live via the Settings tab.
282
+
283
+ | Category | Key | Default | Description |
284
+ |----------|-----|---------|-------------|
285
+ | **Paths** | `master_cv_path` | `templates/my_cv.yaml` | Master CV YAML |
286
+ | | `profile_path` | `profiles/github_repos.json` | GitHub profile JSON |
287
+ | | `opencode_bin_path` | `~/.opencode/bin/opencode` | Path to opencode binary |
288
+ | **Scan** | `scan_queries` | `["python", "rust", "ai engineer"]` | Default scan queries |
289
+ | | `scan_platforms` | `"remoteok,remotive,hn_hiring"` | Default platforms |
290
+ | **Scoring** | `score_weight_*` | `25` each | Category weights (total 100) |
291
+ | | `score_threshold_strong` | `80` | Minimum score for "strong match" |
292
+ | | `score_threshold_good` | `60` | Minimum score for "good match" |
293
+ | | `score_threshold_moderate` | `40` | Minimum score for "moderate match" |
294
+ | **CV Design** | `cv_font_family` | `"Source Sans Pro"` | Font for rendered PDF |
295
+ | | `cv_font_size_body` | `9.5pt` | Body font size |
296
+ | | `cv_line_spacing` | `0.8em` | Line spacing |
297
+ | | `cv_entry_spacing` | `0.2cm` | Space between entries |
298
+ | | `cv_primary_color` | `#2b3a67` | Primary accent color |
299
+ | | `cv_secondary_color` | `#3a5a8c` | Secondary accent color |
300
+ | | `cv_page_margin_*` | `1.0-1.5cm` | Page margins |
301
+ | **ATS** | `ats_ghost_enabled` | `true` | Invisible keyword injection |
302
+ | | `ats_ghost_extra_terms` | `"django, flutter, ..."` | Extra ATS keywords |
303
+ | | `ats_ghost_font_size` | `1` | Font size for ghost text (px) |
304
+ | | `ats_ghost_color` | `#ffffff` | Font color for ghost text |
305
+
306
+ ---
307
+
308
+ ## Constraints
309
+
310
+ - **Never fabricate** experience, skills, metrics, titles, or dates
311
+ - **Preserve all facts** — company names, titles, locations, dates are immutable
312
+ - **Never edit the master CV** — always write a new file to `templates/`
313
+ - **Match JD language** — if the JD says "CI/CD" and your CV says "continuous integration", use "CI/CD"
314
+ - **2 pages max** — drop lower-impact bullets before adding new ones
315
+
316
+ ---
317
+
318
+ ## Troubleshooting
319
+
320
+ | Symptom | Likely Cause | Fix |
321
+ |---------|-------------|-----|
322
+ | `Ctrl+T` does nothing | No job selected | Select a row in the Jobs tab first |
323
+ | Tailor hangs / never completes | opencode binary not found | Set `opencode_bin_path` in Settings tab |
324
+ | Tailor hangs / never completes | opencode timeout (180s default) | Wait — long prompts take time; check Scanner tab for progress |
325
+ | `make render` fails | RenderCV not installed | Run `make install-tools` |
326
+ | Scan returns no results | Platform parser needs update | Try `--platforms hn_hiring` (most stable parser) |
327
+ | Tailored tab is empty | Tailor never succeeded | Check Scanner tab for error messages |
328
+ | `Ctrl+T` says "already in progress" | Previous tailor still running | Wait for completion or restart the TUI |
329
+ | PDF has no content / blank | Incompatible YAML schema | Run `/init-cv` on your master CV to normalize |
330
+ | AI assistant command not found | Skill not loaded | Check `opencode.json` has `.claude/skills` in `skills` array |
331
+ | ATS ghost not working | Feature disabled | Enable `ats_ghost_enabled` in Settings tab |
332
+ | Job URLs not opening | No `open`/`xdg-open` on system | Install `xdg-utils` (Linux) or check OS path |
333
+
334
+ ---
335
+
336
+ ## Architecture
337
+
338
+ ```
339
+ ┌──────────┐ ┌──────────┐ ┌──────────────────┐
340
+ │ TUI │ │ CLI │ │ AI Assistant │
341
+ │ (Textual)│ │ (Python) │ │ (Claude/Codex/OC) │
342
+ └────┬─────┘ └────┬─────┘ └────────┬─────────┘
343
+ │ │ │
344
+ ┌────┴─────────────┴──────────────────┴──────────┐
345
+ │ Python Backend │
346
+ │ tailor_cv.py tailor_brief.py job_matcher.py │
347
+ │ config.py db.py render.py │
348
+ │ job_scanner/ ats_ghost.py │
349
+ └──────────────────────────────────────────────────┘
350
+ │ │ │
351
+ ┌────┴─────────────┴──────────────────┴──────────┐
352
+ │ Storage │
353
+ │ .chameleon/ templates/ output/ profiles/ │
354
+ └──────────────────────────────────────────────────┘
355
+ ```
356
+
357
+ Key design decisions:
358
+ - **Layered architecture** — interfaces never touch storage directly
359
+ - **Subprocess kill registry** — no orphan processes on crash
360
+ - **TeeStream** — stdout from background threads appears in TUI log in real time
361
+ - **Crash-safe notifications** — debug toasts never throw, even during shutdown
362
+
363
+ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for full detail.
364
+
365
+ ---
366
+
367
+ ## OpenCode Integration
368
+
369
+ This project provides `opencode.json` at the root — OpenCode auto-loads it on open:
370
+
371
+ - **12 slash commands** registered with usage hints (`/chameleon`, `/tailor-cv`, `/score-cv`, etc.)
372
+ - **Skill paths**: `.claude/skills/` and `.agents/skills/` scanned for `SKILL.md` definitions
373
+ - **All standard tools** pre-authorized (read, edit, bash, glob, grep, task, webfetch, websearch, question, skill)
374
+ - **Batch tool** enabled for parallel operations
375
+ - **Instructions**: `AGENTS.md` loaded as project context
376
+
377
+ For Claude Code: `CLAUDE.md` (synced copy of AGENTS.md) is auto-loaded on open.
378
+
379
+ ---
380
+
381
+ ## License
382
+
383
+ MIT — see [LICENSE](LICENSE).