jobscout 1.2.0 → 1.4.0
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.
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ npx jobscout setup all # Tất cả
|
|
|
29
29
|
|
|
30
30
|
```
|
|
31
31
|
/plugin marketplace add .
|
|
32
|
-
/plugin install
|
|
32
|
+
/plugin install jobscout
|
|
33
33
|
/find-jobs path/to/CV.pdf
|
|
34
34
|
```
|
|
35
35
|
|
|
@@ -97,7 +97,7 @@ JSON schema trong `job-matching-plugin/schemas/`:
|
|
|
97
97
|
## Cấu trúc repo
|
|
98
98
|
|
|
99
99
|
```
|
|
100
|
-
├── bin/cli.mjs ← CLI (npx
|
|
100
|
+
├── bin/cli.mjs ← CLI (npx jobscout setup)
|
|
101
101
|
├── job-matching-plugin/ ← nguồn chân lý duy nhất
|
|
102
102
|
│ ├── .claude-plugin/ Claude Code manifest
|
|
103
103
|
│ ├── .codex-plugin/ Codex CLI manifest
|
package/bin/cli.mjs
CHANGED
|
@@ -52,6 +52,16 @@ function ensureDir(dir) {
|
|
|
52
52
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// Copy a file, rewriting plugin-relative schema paths to the target layout.
|
|
56
|
+
function copyFileRewrite(src, dest, schemaPath = ".claude/schemas/") {
|
|
57
|
+
let text = readFileSync(src, "utf8");
|
|
58
|
+
text = text
|
|
59
|
+
.replace(/\$\{CLAUDE_PLUGIN_ROOT\}\/schemas\//g, schemaPath)
|
|
60
|
+
.replace(/\.\/schemas\//g, schemaPath);
|
|
61
|
+
ensureDir(dirname(dest));
|
|
62
|
+
writeFileSync(dest, text);
|
|
63
|
+
}
|
|
64
|
+
|
|
55
65
|
function detectPlatforms() {
|
|
56
66
|
const platforms = [];
|
|
57
67
|
if (existsSync(join(CWD, ".claude")) || process.env.CLAUDE_CODE) {
|
|
@@ -63,56 +73,108 @@ function detectPlatforms() {
|
|
|
63
73
|
return platforms;
|
|
64
74
|
}
|
|
65
75
|
|
|
76
|
+
// Skills cần cho Claude — bỏ find-jobs/job-collector/job-matcher (command + agents đã lo).
|
|
77
|
+
const CLAUDE_SKILLS = [
|
|
78
|
+
"candidate-intake",
|
|
79
|
+
"scoring-rubric",
|
|
80
|
+
"job-schema",
|
|
81
|
+
"bilingual-normalization",
|
|
82
|
+
"fit-analyzer",
|
|
83
|
+
"application-assistant"
|
|
84
|
+
];
|
|
85
|
+
|
|
66
86
|
function setupClaude() {
|
|
67
87
|
heading("Claude Code");
|
|
68
88
|
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
const dotClaude = join(CWD, ".claude");
|
|
90
|
+
const agentsDest = join(dotClaude, "agents");
|
|
91
|
+
const commandsDest = join(dotClaude, "commands");
|
|
92
|
+
const skillsDest = join(dotClaude, "skills");
|
|
93
|
+
const schemasDest = join(dotClaude, "schemas");
|
|
94
|
+
|
|
95
|
+
[agentsDest, commandsDest, skillsDest, schemasDest].forEach(ensureDir);
|
|
96
|
+
|
|
97
|
+
// Schemas (nguồn dùng chung, không rewrite nội dung JSON).
|
|
98
|
+
const schemasSrc = join(PLUGIN_SRC, "schemas");
|
|
99
|
+
copyDir(schemasSrc, schemasDest);
|
|
100
|
+
ok("Copy .claude/schemas/ (profile, job, match)");
|
|
101
|
+
|
|
102
|
+
// Agents — chạy context riêng cho bước tốn token.
|
|
103
|
+
["job-collector", "job-matcher"].forEach((name) => {
|
|
104
|
+
copyFileRewrite(
|
|
105
|
+
join(PLUGIN_SRC, "agents", `${name}.md`),
|
|
106
|
+
join(agentsDest, `${name}.md`)
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
ok("Copy .claude/agents/ (job-collector, job-matcher)");
|
|
110
|
+
|
|
111
|
+
// Command /find-jobs.
|
|
112
|
+
copyFileRewrite(
|
|
113
|
+
join(PLUGIN_SRC, "commands", "find-jobs.md"),
|
|
114
|
+
join(commandsDest, "find-jobs.md")
|
|
94
115
|
);
|
|
95
|
-
ok("
|
|
116
|
+
ok("Copy .claude/commands/find-jobs.md → slash command /find-jobs");
|
|
96
117
|
|
|
97
|
-
|
|
98
|
-
|
|
118
|
+
// Skills.
|
|
119
|
+
CLAUDE_SKILLS.forEach((name) => {
|
|
120
|
+
copyFileRewrite(
|
|
121
|
+
join(PLUGIN_SRC, "skills", name, "SKILL.md"),
|
|
122
|
+
join(skillsDest, name, "SKILL.md")
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
ok(`Copy .claude/skills/ (${CLAUDE_SKILLS.length} skills)`);
|
|
99
126
|
|
|
100
127
|
log("");
|
|
101
|
-
info("
|
|
102
|
-
log(` ${CYAN}/plugin marketplace add .${RESET}`);
|
|
103
|
-
log(` ${CYAN}/plugin install job-matching${RESET}`);
|
|
128
|
+
info("Xong! Trong Claude Code (thư mục này) chạy luôn:");
|
|
104
129
|
log(` ${CYAN}/find-jobs path/to/CV.pdf${RESET}`);
|
|
130
|
+
log(` ${DIM}Không cần /plugin install — Claude Code tự nhận .claude/${RESET}`);
|
|
105
131
|
}
|
|
106
132
|
|
|
107
133
|
function setupCodex() {
|
|
108
134
|
heading("Codex CLI");
|
|
109
135
|
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
136
|
+
const dotAgents = join(CWD, ".agents");
|
|
137
|
+
const agentsDest = join(dotAgents, "agents");
|
|
138
|
+
const commandsDest = join(dotAgents, "commands");
|
|
139
|
+
const skillsDest = join(dotAgents, "skills");
|
|
140
|
+
const schemasDest = join(dotAgents, "schemas");
|
|
141
|
+
|
|
142
|
+
[agentsDest, commandsDest, skillsDest, schemasDest].forEach(ensureDir);
|
|
143
|
+
|
|
144
|
+
// Schemas.
|
|
145
|
+
copyDir(join(PLUGIN_SRC, "schemas"), schemasDest);
|
|
146
|
+
ok("Copy .agents/schemas/ (profile, job, match)");
|
|
147
|
+
|
|
148
|
+
// Agents.
|
|
149
|
+
["job-collector", "job-matcher"].forEach((name) => {
|
|
150
|
+
copyFileRewrite(
|
|
151
|
+
join(PLUGIN_SRC, "agents", `${name}.md`),
|
|
152
|
+
join(agentsDest, `${name}.md`),
|
|
153
|
+
".agents/schemas/"
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
ok("Copy .agents/agents/ (job-collector, job-matcher)");
|
|
157
|
+
|
|
158
|
+
// Command.
|
|
159
|
+
copyFileRewrite(
|
|
160
|
+
join(PLUGIN_SRC, "commands", "find-jobs.md"),
|
|
161
|
+
join(commandsDest, "find-jobs.md"),
|
|
162
|
+
".agents/schemas/"
|
|
163
|
+
);
|
|
164
|
+
ok("Copy .agents/commands/find-jobs.md");
|
|
165
|
+
|
|
166
|
+
// Skills.
|
|
167
|
+
CLAUDE_SKILLS.forEach((name) => {
|
|
168
|
+
copyFileRewrite(
|
|
169
|
+
join(PLUGIN_SRC, "skills", name, "SKILL.md"),
|
|
170
|
+
join(skillsDest, name, "SKILL.md"),
|
|
171
|
+
".agents/schemas/"
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
ok(`Copy .agents/skills/ (${CLAUDE_SKILLS.length} skills)`);
|
|
113
175
|
|
|
114
176
|
log("");
|
|
115
|
-
info("Chạy Codex:");
|
|
177
|
+
info("Xong! Chạy Codex trong thư mục này:");
|
|
116
178
|
log(` ${CYAN}codex --search${RESET} ${DIM}# bật web search${RESET}`);
|
|
117
179
|
log(` Gọi skill ${CYAN}find-jobs${RESET} với đường dẫn CV.`);
|
|
118
180
|
}
|
|
@@ -144,7 +206,7 @@ function setupChatgpt() {
|
|
|
144
206
|
}
|
|
145
207
|
|
|
146
208
|
function runSetup(platform) {
|
|
147
|
-
log(`${BOLD}🔧
|
|
209
|
+
log(`${BOLD}🔧 JobScout Setup${RESET}`);
|
|
148
210
|
|
|
149
211
|
if (!platform) {
|
|
150
212
|
const detected = detectPlatforms();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "jobscout",
|
|
3
3
|
"version": "1.2.0",
|
|
4
4
|
"description": "Tìm và xếp hạng job phù hợp nhất với target + CV của ứng viên. Pipeline: parse CV → thu thập job (chỉ job xem được & còn hạn) → chấm điểm theo rubric → báo cáo fit/gap. Song ngữ Việt-Anh.",
|
|
5
5
|
"author": {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "jobscout",
|
|
3
3
|
"version": "1.2.0",
|
|
4
4
|
"description": "Tìm và xếp hạng việc làm phù hợp với mục tiêu nghề nghiệp và CV song ngữ Việt–Anh, thu thập job từ web search.",
|
|
5
5
|
"author": {"name": "Nguyen Trong Hieu", "email": "hieutrong512@gmail.com"},
|
|
6
6
|
"keywords": ["jobs", "career", "cv", "vietnam"],
|
|
7
7
|
"skills": "./skills/",
|
|
8
8
|
"interface": {
|
|
9
|
-
"displayName": "
|
|
9
|
+
"displayName": "JobScout",
|
|
10
10
|
"shortDescription": "Tìm và xếp hạng việc làm phù hợp từ CV",
|
|
11
11
|
"longDescription": "Pipeline song ngữ Việt–Anh để đọc CV, thu thập việc làm từ web search, chấm điểm và tạo báo cáo mức độ phù hợp.",
|
|
12
|
-
"developerName": "
|
|
12
|
+
"developerName": "JobScout",
|
|
13
13
|
"category": "Productivity",
|
|
14
14
|
"capabilities": ["Read", "Write", "Interactive"],
|
|
15
15
|
"defaultPrompt": ["Tìm việc làm phù hợp từ CV này.", "Phân tích CV và tạo danh sách việc làm phù hợp nhất."],
|
|
@@ -11,7 +11,7 @@ Thêm marketplace rồi cài plugin (trong phiên `claude` tương tác):
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
/plugin install
|
|
14
|
+
/plugin install jobscout
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
> Marketplace nằm ở `.claude-plugin/marketplace.json` tại gốc repo; plugin nằm trong `job-matching-plugin/`.
|
package/package.json
CHANGED