@phuthuycoding/markcv 0.1.0 → 0.1.2
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/CHANGELOG.md +66 -0
- package/README.md +24 -38
- package/dist/cli.js +11 -1
- package/dist/mcp/server.js +2 -1
- package/dist/version.d.ts +1 -0
- package/dist/version.js +21 -0
- package/package.json +5 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.2] - 2026-09-06
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- `markcv --version` reported the version that was hardcoded in the source rather
|
|
15
|
+
than the one actually installed: 0.1.1 shipped while `--version` still said
|
|
16
|
+
0.1.0. Both the CLI and the MCP server now read it from `package.json`, and a
|
|
17
|
+
test fails if the two ever disagree.
|
|
18
|
+
|
|
19
|
+
## [0.1.1] - 2026-09-06
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- `markcv mcp` subcommand, so MCP clients can use the shape everyone else uses:
|
|
24
|
+
`npx -y @phuthuycoding/markcv mcp`. With two binaries in the package, the bare
|
|
25
|
+
`npx` form would otherwise need `--package=…`, which nobody writes from memory.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- README now leads with installing from npm, and no longer asks the reader to
|
|
30
|
+
clone and build. Development setup moved to `CONTRIBUTING.md`.
|
|
31
|
+
- MCP documentation defaults to the `npx` form; the global `markcv-mcp` binary is
|
|
32
|
+
presented as the faster alternative rather than the only way.
|
|
33
|
+
- `render --no-photo` reports `photo disabled` instead of
|
|
34
|
+
`photo none (placeholder box)` — not embedding a photo and not finding one are
|
|
35
|
+
different things.
|
|
36
|
+
|
|
37
|
+
## [0.1.0] - 2026-09-06
|
|
38
|
+
|
|
39
|
+
First release.
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- `fit` — explains *why* a CV does not fit a page target, separating content that
|
|
44
|
+
is genuinely too long from content pushed onto a new page by a bad break, and
|
|
45
|
+
naming the block responsible with the pixels it wasted.
|
|
46
|
+
- `lint` — audits content rather than formatting: overselling (`spearheaded`,
|
|
47
|
+
`comprehensive`), **underselling** (`advised on` next to work of real scale),
|
|
48
|
+
present-tense bullets on finished jobs, skills claimed with no supporting
|
|
49
|
+
experience, duplicate bullets, IC/manager role mismatch, bullets without a
|
|
50
|
+
single number, emoji in headings, and over-long bullets.
|
|
51
|
+
- `tailor` — compares a CV against a job description: requirements with no
|
|
52
|
+
evidence, keywords that appear only under SKILLS, and bullets unrelated to the
|
|
53
|
+
role.
|
|
54
|
+
- `render` — Markdown to A4 PDF via a system Chrome, with portrait photo
|
|
55
|
+
auto-detection and a warning when the photo will bloat the PDF.
|
|
56
|
+
- `new`, `list`, `diff`, `build` — master/variant workflow for keeping one content
|
|
57
|
+
store and cutting tailored copies from it.
|
|
58
|
+
- MCP server exposing seven tools that return structured JSON, so an agent can
|
|
59
|
+
iterate: edit → `check_fit` → read `culprits` → edit again.
|
|
60
|
+
- Two ATS-safe themes: `classic` and `compact`.
|
|
61
|
+
- Example CVs in `examples/`, with and without a portrait photo.
|
|
62
|
+
|
|
63
|
+
[Unreleased]: https://github.com/phuthuycoding/markcv/compare/v0.1.2...HEAD
|
|
64
|
+
[0.1.2]: https://github.com/phuthuycoding/markcv/compare/v0.1.1...v0.1.2
|
|
65
|
+
[0.1.1]: https://github.com/phuthuycoding/markcv/compare/v0.1.0...v0.1.1
|
|
66
|
+
[0.1.0]: https://github.com/phuthuycoding/markcv/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -19,20 +19,17 @@ Two things set it apart from ordinary markdown→PDF tools:
|
|
|
19
19
|
## Install
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
|
|
23
|
-
cd markcv
|
|
24
|
-
npm install # builds dist/ via the prepare script
|
|
25
|
-
npm link # puts `markcv` and `markcv-mcp` on your PATH
|
|
22
|
+
npm install -g @phuthuycoding/markcv
|
|
26
23
|
```
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
The package is scoped; the commands are not. You type `markcv` and `markcv-mcp`.
|
|
26
|
+
|
|
27
|
+
Or run it without installing:
|
|
29
28
|
|
|
30
29
|
```bash
|
|
31
|
-
|
|
30
|
+
npx @phuthuycoding/markcv fit cv.md --pages 2
|
|
32
31
|
```
|
|
33
32
|
|
|
34
|
-
The package is scoped, but the commands are not — you still type `markcv` and `markcv-mcp`.
|
|
35
|
-
|
|
36
33
|
Requires a Chromium-based browser already on your machine (Chrome, Chromium, Edge, Brave). markcv deliberately does **not** download its own Chromium — it uses `puppeteer-core`, so the install stays small. If your browser lives somewhere unusual, point at it with `MARKCV_CHROME=/path/to/chrome`.
|
|
37
34
|
|
|
38
35
|
## Usage
|
|
@@ -129,61 +126,49 @@ Note what the bullets in those samples have in common: a number, or a before and
|
|
|
129
126
|
|
|
130
127
|
Lets an AI agent (Claude Code, Claude Desktop, Cursor…) build and audit CVs on its own.
|
|
131
128
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
Check the server starts (it waits for JSON-RPC on stdin and prints nothing — that is
|
|
135
|
-
correct; Ctrl+C to quit):
|
|
136
|
-
|
|
137
|
-
```bash
|
|
138
|
-
markcv-mcp
|
|
139
|
-
```
|
|
129
|
+
Nothing to install: `npx` fetches the package on first use and caches it.
|
|
140
130
|
|
|
141
131
|
### Register it with a client
|
|
142
132
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
**Claude Code** — add to `.mcp.json` in your project (shared with the team), or `~/.claude.json` (just you):
|
|
133
|
+
**Claude Code** — add to `.mcp.json` in your project (shared with the team), or
|
|
134
|
+
`~/.claude.json` (just you):
|
|
147
135
|
|
|
148
136
|
```json
|
|
149
137
|
{
|
|
150
138
|
"mcpServers": {
|
|
151
139
|
"markcv": {
|
|
152
|
-
"command": "
|
|
140
|
+
"command": "npx",
|
|
141
|
+
"args": ["-y", "@phuthuycoding/markcv", "mcp"],
|
|
153
142
|
"cwd": "/path/to/your/cv/folder"
|
|
154
143
|
}
|
|
155
144
|
}
|
|
156
145
|
}
|
|
157
146
|
```
|
|
158
147
|
|
|
159
|
-
Or
|
|
148
|
+
Or from the command line:
|
|
160
149
|
|
|
161
150
|
```bash
|
|
162
|
-
claude mcp add markcv -- markcv
|
|
151
|
+
claude mcp add markcv -- npx -y @phuthuycoding/markcv mcp
|
|
163
152
|
claude mcp list # confirm it connected
|
|
164
153
|
```
|
|
165
154
|
|
|
166
155
|
Restart the client afterwards so it picks the server up.
|
|
167
156
|
|
|
168
|
-
|
|
157
|
+
If you installed the package globally, `"command": "markcv-mcp"` with no `args`
|
|
158
|
+
works too and starts marginally faster. The repo ships `.mcp.json.example` with
|
|
159
|
+
both shapes.
|
|
160
|
+
|
|
161
|
+
**Claude Desktop** — `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
162
|
+
(macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows), same shape,
|
|
163
|
+
then restart the app.
|
|
169
164
|
|
|
170
165
|
**Cursor** — `.cursor/mcp.json` in the project, same shape.
|
|
171
166
|
|
|
172
167
|
### File paths in tool arguments
|
|
173
168
|
|
|
174
|
-
Every tool takes a file path
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
{
|
|
178
|
-
"mcpServers": {
|
|
179
|
-
"markcv": {
|
|
180
|
-
"command": "node",
|
|
181
|
-
"args": ["/path/to/markcv/dist/mcp/server.js"],
|
|
182
|
-
"cwd": "/path/to/your/cv/folder"
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
```
|
|
169
|
+
Every tool takes a file path, and relative paths resolve against the **server
|
|
170
|
+
process's working directory** — hence the `cwd` above. Without it, pass absolute
|
|
171
|
+
paths instead.
|
|
187
172
|
|
|
188
173
|
### Tools
|
|
189
174
|
|
|
@@ -201,7 +186,8 @@ Every tool returns **structured JSON**, not prose — so an agent can loop on it
|
|
|
201
186
|
|
|
202
187
|
### Requirements
|
|
203
188
|
|
|
204
|
-
Node >= 18 and a Chromium-based browser
|
|
189
|
+
Node >= 18 and a Chromium-based browser (only `render` and `check_fit` need it).
|
|
190
|
+
If it is in a non-standard location:
|
|
205
191
|
|
|
206
192
|
```json
|
|
207
193
|
{ "mcpServers": { "markcv": { "command": "node", "args": ["..."],
|
package/dist/cli.js
CHANGED
|
@@ -8,8 +8,9 @@ import { lint } from "./core/lint.js";
|
|
|
8
8
|
import { tailor } from "./core/tailor.js";
|
|
9
9
|
import { newVariant, listVariants, diffVariants } from "./core/variants.js";
|
|
10
10
|
import { c, ok, bad, warn, info } from "./ui.js";
|
|
11
|
+
import { VERSION } from "./version.js";
|
|
11
12
|
const program = new Command();
|
|
12
|
-
program.name("markcv").description("Build, fit and audit a CV written in Markdown").version(
|
|
13
|
+
program.name("markcv").description("Build, fit and audit a CV written in Markdown").version(VERSION);
|
|
13
14
|
const pdfNameFor = (md) => md.replace(/\.md$/, ".pdf");
|
|
14
15
|
function printFit(r) {
|
|
15
16
|
const head = r.fits ? ok(`${r.pages} page(s)`) : bad(`${r.pages} pages (target ${r.targetPages})`);
|
|
@@ -185,4 +186,13 @@ program
|
|
|
185
186
|
console.log(`${mark} ${f.padEnd(34)} ${fit.pages} page(s) ${c.dim(fit.fits ? "" : fit.suggestions[0] ?? "")}`);
|
|
186
187
|
}
|
|
187
188
|
});
|
|
189
|
+
program
|
|
190
|
+
.command("mcp")
|
|
191
|
+
.description("Start the MCP server on stdio (for AI agent clients)")
|
|
192
|
+
.action(async () => {
|
|
193
|
+
// Importing the server starts it: it connects to stdio and stays there.
|
|
194
|
+
// Having it as a subcommand is what lets `npx @scope/pkg mcp` work without
|
|
195
|
+
// the --package dance a second binary would need.
|
|
196
|
+
await import("./mcp/server.js");
|
|
197
|
+
});
|
|
188
198
|
program.parseAsync(process.argv);
|
package/dist/mcp/server.js
CHANGED
|
@@ -10,7 +10,8 @@ import { analyseFit } from "../core/fit.js";
|
|
|
10
10
|
import { lint } from "../core/lint.js";
|
|
11
11
|
import { tailor } from "../core/tailor.js";
|
|
12
12
|
import { newVariant, listVariants, diffVariants } from "../core/variants.js";
|
|
13
|
-
|
|
13
|
+
import { VERSION } from "../version.js";
|
|
14
|
+
const server = new McpServer({ name: "markcv", version: VERSION });
|
|
14
15
|
/** Every tool returns JSON so an agent can loop on the result, rather than prose for a human. */
|
|
15
16
|
const json = (data) => ({
|
|
16
17
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION: string;
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
/**
|
|
5
|
+
* Read the version from package.json instead of hardcoding it.
|
|
6
|
+
* A hardcoded copy silently goes stale the moment a release is cut, and then
|
|
7
|
+
* `--version` reports one thing while the installed code is another.
|
|
8
|
+
*/
|
|
9
|
+
function readVersion() {
|
|
10
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
for (const rel of ["../package.json", "../../package.json"]) {
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(readFileSync(join(here, rel), "utf8")).version;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// try the next candidate: dist/ is one level deeper than src/
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return "0.0.0";
|
|
20
|
+
}
|
|
21
|
+
export const VERSION = readVersion();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phuthuycoding/markcv",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Fit, lint and build a CV from Markdown - CLI + MCP server for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"dist",
|
|
16
16
|
"themes",
|
|
17
17
|
"README.md",
|
|
18
|
-
"LICENSE"
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"CHANGELOG.md"
|
|
19
20
|
],
|
|
20
21
|
"engines": {
|
|
21
22
|
"node": ">=18"
|
|
@@ -26,7 +27,8 @@
|
|
|
26
27
|
"mcp": "node dist/mcp/server.js",
|
|
27
28
|
"test": "node --test test/*.test.js",
|
|
28
29
|
"prepublishOnly": "npm run build",
|
|
29
|
-
"prepare": "npm run build"
|
|
30
|
+
"prepare": "npm run build",
|
|
31
|
+
"changelog": "node scripts/changelog.mjs"
|
|
30
32
|
},
|
|
31
33
|
"keywords": [
|
|
32
34
|
"cv",
|