@getkrafter/resume-toolkit 1.0.5 → 1.1.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/dist/bin/cli.js CHANGED
@@ -1,4 +1,61 @@
1
1
  #!/usr/bin/env node
2
2
  import { startServer } from '../mcp/server.js';
3
- startServer();
3
+ import { scoreResume } from '../lib/resume-scorer.js';
4
+ import { scoreATS } from '../lib/ats-scorer.js';
5
+ const args = process.argv.slice(2);
6
+ const command = args[0];
7
+ if (command === 'score') {
8
+ const resumeFile = getFlag(args, '--resume');
9
+ const jdFile = getFlag(args, '--jd');
10
+ if (!resumeFile) {
11
+ console.error('Usage: resume-toolkit score --resume <file> [--jd <file>]');
12
+ process.exit(1);
13
+ }
14
+ const fs = await import('node:fs');
15
+ const resumeText = fs.readFileSync(resumeFile, 'utf-8');
16
+ const jdText = jdFile ? fs.readFileSync(jdFile, 'utf-8') : undefined;
17
+ const resumeData = parseRawText(resumeText);
18
+ const result = scoreResume(resumeData, jdText);
19
+ console.log(JSON.stringify(result, null, 2));
20
+ }
21
+ else if (command === 'ats') {
22
+ const resumeFile = getFlag(args, '--resume');
23
+ const jdFile = getFlag(args, '--jd');
24
+ if (!resumeFile || !jdFile) {
25
+ console.error('Usage: resume-toolkit ats --resume <file> --jd <file>');
26
+ process.exit(1);
27
+ }
28
+ const fs = await import('node:fs');
29
+ const resumeText = fs.readFileSync(resumeFile, 'utf-8');
30
+ const jdText = fs.readFileSync(jdFile, 'utf-8');
31
+ const result = scoreATS(resumeText, jdText);
32
+ console.log(JSON.stringify(result, null, 2));
33
+ }
34
+ else {
35
+ // Default: start MCP server
36
+ startServer();
37
+ }
38
+ function getFlag(args, flag) {
39
+ const idx = args.indexOf(flag);
40
+ return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
41
+ }
42
+ function parseRawText(text) {
43
+ const lines = text.split('\n');
44
+ const bullets = [];
45
+ const sections = [];
46
+ for (const line of lines) {
47
+ const trimmed = line.trim();
48
+ if (!trimmed)
49
+ continue;
50
+ if (/^\s*[-*•]\s+/.test(line) || /^\s*\d+[.)]\s+/.test(line)) {
51
+ bullets.push(trimmed.replace(/^[-*•]\s+/, '').replace(/^\d+[.)]\s+/, ''));
52
+ }
53
+ else if (trimmed.length < 50 &&
54
+ (trimmed === trimmed.toUpperCase() || /^[A-Z][a-z]/.test(trimmed)) &&
55
+ !/^\s*[-*•]|\d+[.)]/.test(trimmed)) {
56
+ sections.push(trimmed.toLowerCase());
57
+ }
58
+ }
59
+ return { rawText: text, bullets, sections };
60
+ }
4
61
  //# sourceMappingURL=cli.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bin/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bin/cli.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getkrafter/resume-toolkit",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "Deterministic resume scoring, ATS keyword matching, and AI-powered resume tailoring",
5
5
  "type": "module",
6
6
  "exports": {
@@ -91,29 +91,21 @@ Or for Krafter resumes, call `score_krafter_resume`:
91
91
  }
92
92
  ```
93
93
 
94
- **Option B — No MCP server** (skill installed without MCP):
94
+ **Option B — CLI** (no MCP server needed):
95
95
 
96
- Run this inline script to score the resume. Replace the `resumeText` and `jdText` values with the actual content:
96
+ 1. Write the resume text to a temp file (e.g., `/tmp/resume.txt`).
97
+ 2. If a JD was provided, write it to another temp file (e.g., `/tmp/jd.txt`).
98
+ 3. Run:
97
99
 
98
100
  ```bash
99
- node --input-type=module -e "
100
- import { scoreResume, scoreATS } from '@getkrafter/resume-toolkit';
101
+ # Without JD:
102
+ npx @getkrafter/resume-toolkit score --resume /tmp/resume.txt
101
103
 
102
- const resumeText = process.env.RESUME_TEXT;
103
- const jdText = process.env.JD_TEXT || '';
104
-
105
- const lines = resumeText.split('\n');
106
- const bullets = lines.filter(l => /^\s*[-*•]|\d+[.)]/.test(l)).map(l => l.replace(/^\s*[-*•]\s*|\d+[.)]\s*/, '').trim());
107
- const sections = lines.filter(l => l.trim().length < 50 && l.trim().length > 0 && !(/^\s*[-*•]|\d+[.)]/.test(l)) && (l.trim() === l.trim().toUpperCase() || /^[A-Z][a-z]/.test(l.trim()))).map(l => l.trim().toLowerCase());
108
-
109
- const result = scoreResume({ rawText: resumeText, bullets, sections }, jdText || undefined);
110
- console.log(JSON.stringify(result, null, 2));
111
- " <<< ""
104
+ # With JD:
105
+ npx @getkrafter/resume-toolkit score --resume /tmp/resume.txt --jd /tmp/jd.txt
112
106
  ```
113
107
 
114
- Pass `RESUME_TEXT` and `JD_TEXT` as environment variables containing the resume and job description text. Parse the JSON output and present results per Step 6.
115
-
116
- If `@getkrafter/resume-toolkit` is not installed as a dependency, install it first: `npm install @getkrafter/resume-toolkit`
108
+ The output is a JSON `ResumeScore` object. Parse it and present results per Step 6.
117
109
 
118
110
  ---
119
111
 
@@ -67,28 +67,20 @@ For pasted/file resumes:
67
67
  For Krafter resumes:
68
68
  1. `score_krafter_resume` with `{ id, jdText }` -- returns the full `ResumeScore` including the embedded `ATSResult`.
69
69
 
70
- **Option B — No MCP server** (skill installed without MCP):
70
+ **Option B — CLI** (no MCP server needed):
71
71
 
72
- Run this inline script. Pass `RESUME_TEXT` and `JD_TEXT` as environment variables:
72
+ 1. Write the resume text to `/tmp/resume.txt` and the JD to `/tmp/jd.txt`.
73
+ 2. Run both commands:
73
74
 
74
75
  ```bash
75
- node --input-type=module -e "
76
- import { scoreResume, scoreATS } from '@getkrafter/resume-toolkit';
76
+ # Full score with ATS:
77
+ npx @getkrafter/resume-toolkit score --resume /tmp/resume.txt --jd /tmp/jd.txt
77
78
 
78
- const resumeText = process.env.RESUME_TEXT;
79
- const jdText = process.env.JD_TEXT;
80
-
81
- const lines = resumeText.split('\n');
82
- const bullets = lines.filter(l => /^\s*[-*•]|\d+[.)]/.test(l)).map(l => l.replace(/^\s*[-*•]\s*|\d+[.)]\s*/, '').trim());
83
- const sections = lines.filter(l => l.trim().length < 50 && l.trim().length > 0 && !(/^\s*[-*•]|\d+[.)]/.test(l)) && (l.trim() === l.trim().toUpperCase() || /^[A-Z][a-z]/.test(l.trim()))).map(l => l.trim().toLowerCase());
84
-
85
- const atsResult = scoreATS(resumeText, jdText);
86
- const scoreResult = scoreResume({ rawText: resumeText, bullets, sections }, jdText);
87
- console.log(JSON.stringify({ atsResult, scoreResult }, null, 2));
88
- " <<< ""
79
+ # Standalone ATS analysis:
80
+ npx @getkrafter/resume-toolkit ats --resume /tmp/resume.txt --jd /tmp/jd.txt
89
81
  ```
90
82
 
91
- If `@getkrafter/resume-toolkit` is not installed, run `npm install @getkrafter/resume-toolkit` first. Parse the JSON output and continue to Step 5.
83
+ Parse the JSON output from each command and continue to Step 5.
92
84
 
93
85
  ### Step 5 -- Gap Analysis
94
86