job-apply-plugin 0.2.0 → 0.3.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/.claude-plugin/marketplace.json +1 -1
- package/README.md +28 -7
- package/bin/job-apply.js +49 -16
- package/package.json +9 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/plugin.json +1 -1
package/README.md
CHANGED
|
@@ -74,24 +74,45 @@ npm install -g job-apply-plugin && job-apply-plugin install
|
|
|
74
74
|
The installer never overwrites a folder it didn't create unless you pass `--force`.
|
|
75
75
|
When you add Job Apply to an existing `marketplace.json`, the other entries in that file are kept.
|
|
76
76
|
|
|
77
|
+
## Uninstall
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npx job-apply-plugin uninstall
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
It asks which app to remove Job Apply from, and shows where it's currently installed:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Remove Job Apply from which app?
|
|
87
|
+
1) Claude Code (installed v0.3.0)
|
|
88
|
+
2) ChatGPT desktop / Codex (not installed)
|
|
89
|
+
3) Both
|
|
90
|
+
Choose 1, 2 or 3 [1]:
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
To skip the menu, use `--claude`, `--chatgpt` or `--all`. `remove` works as another name for `uninstall`.
|
|
94
|
+
For ChatGPT, also click **Uninstall** on its Plugins page, then restart the app.
|
|
95
|
+
|
|
96
|
+
Uninstalling keeps your résumé, profile and application history in `~/Documents/Job Apply`.
|
|
97
|
+
To erase those too, ask the assistant to "clear my Job Apply profile" before you uninstall,
|
|
98
|
+
or delete that folder.
|
|
99
|
+
|
|
100
|
+
> `npm uninstall -g job-apply-plugin` only removes the installer, not the plugin.
|
|
101
|
+
> Run `uninstall` first.
|
|
102
|
+
|
|
77
103
|
## Other commands
|
|
78
104
|
|
|
79
105
|
```bash
|
|
80
106
|
npx job-apply-plugin status # where it's installed and whether Python is OK
|
|
81
107
|
npx job-apply-plugin install # run again to update
|
|
82
|
-
npx job-apply-plugin uninstall # removes it from both apps and keeps your profile and history
|
|
83
|
-
npx job-apply-plugin uninstall --chatgpt # or from just one app (--claude / --chatgpt)
|
|
84
108
|
```
|
|
85
109
|
|
|
86
|
-
To erase your saved profile and history, ask the assistant to "clear my Job Apply profile",
|
|
87
|
-
or delete `~/Documents/Job Apply`.
|
|
88
|
-
|
|
89
110
|
## Installing from the Git repository (alternative)
|
|
90
111
|
|
|
91
112
|
The repository is also a plugin marketplace for both apps.
|
|
92
113
|
|
|
93
|
-
- Claude Code: `claude plugin marketplace add
|
|
94
|
-
- Codex: `codex plugin marketplace add
|
|
114
|
+
- Claude Code: `claude plugin marketplace add filipelinemburger/job-apply` then `claude plugin install job-apply@job-apply`
|
|
115
|
+
- Codex: `codex plugin marketplace add https://github.com/filipelinemburger/job-apply.git`
|
|
95
116
|
|
|
96
117
|
## Privacy
|
|
97
118
|
|
package/bin/job-apply.js
CHANGED
|
@@ -232,7 +232,8 @@ Usage
|
|
|
232
232
|
|
|
233
233
|
Commands
|
|
234
234
|
install Install (or update) the plugin
|
|
235
|
-
uninstall Remove the plugin
|
|
235
|
+
uninstall Remove the plugin from Claude Code, ChatGPT or both (alias: remove).
|
|
236
|
+
Your profile and history in ~/Documents/Job Apply are kept.
|
|
236
237
|
status Show where the plugin is installed and check Python
|
|
237
238
|
|
|
238
239
|
Options
|
|
@@ -246,7 +247,7 @@ Options
|
|
|
246
247
|
|
|
247
248
|
Run "install" with no app flag to pick from a menu: Claude Code, ChatGPT, or both.
|
|
248
249
|
Without a terminal to ask in (CI, scripts), it installs into the apps found on this computer.
|
|
249
|
-
"uninstall" with no app flag
|
|
250
|
+
"uninstall" with no app flag shows the same menu (without a terminal, it removes from both).`;
|
|
250
251
|
|
|
251
252
|
const CHOICES = {
|
|
252
253
|
1: ["claude"],
|
|
@@ -271,16 +272,16 @@ function flagTargets(values) {
|
|
|
271
272
|
return chosen;
|
|
272
273
|
}
|
|
273
274
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
const
|
|
277
|
-
log(
|
|
278
|
-
log(` 1) Claude Code${
|
|
279
|
-
log(` 2) ChatGPT desktop / Codex${
|
|
275
|
+
// Shows the 1/2/3 menu. `notes` maps each target to a hint shown next to it; `verb` is "installed" or "removed".
|
|
276
|
+
async function askTargets({ title, notes, defaultChoice, verb }) {
|
|
277
|
+
const cancelled = `Cancelled. Nothing was ${verb}.`;
|
|
278
|
+
log(title);
|
|
279
|
+
log(` 1) Claude Code${notes(claude)}`);
|
|
280
|
+
log(` 2) ChatGPT desktop / Codex${notes(chatgpt)}`);
|
|
280
281
|
log(` 3) Both`);
|
|
281
282
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
282
283
|
rl.on("SIGINT", () => {
|
|
283
|
-
log(
|
|
284
|
+
log(`\n${cancelled}`);
|
|
284
285
|
process.exit(130);
|
|
285
286
|
});
|
|
286
287
|
try {
|
|
@@ -290,7 +291,7 @@ async function askTargets(found) {
|
|
|
290
291
|
answer = await rl.question(`Choose 1, 2 or 3 [${defaultChoice}]: `);
|
|
291
292
|
} catch (err) {
|
|
292
293
|
// Ctrl+D or a closed terminal
|
|
293
|
-
if (err?.name === "AbortError" || err?.code === "ABORT_ERR") throw new CliError(
|
|
294
|
+
if (err?.name === "AbortError" || err?.code === "ABORT_ERR") throw new CliError(cancelled);
|
|
294
295
|
throw err;
|
|
295
296
|
}
|
|
296
297
|
const ids = parseChoice(answer, defaultChoice);
|
|
@@ -303,20 +304,49 @@ async function askTargets(found) {
|
|
|
303
304
|
} finally {
|
|
304
305
|
rl.close();
|
|
305
306
|
}
|
|
306
|
-
throw new CliError(
|
|
307
|
+
throw new CliError(`No choice made. Nothing was ${verb}.`);
|
|
307
308
|
}
|
|
308
309
|
|
|
310
|
+
const interactive = () => Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
311
|
+
const choiceFor = (list) => (list.length === 1 ? (list[0] === claude ? "1" : "2") : "3");
|
|
312
|
+
|
|
309
313
|
async function pickInstallTargets(values) {
|
|
310
314
|
const flagged = flagTargets(values);
|
|
311
315
|
if (flagged.length) return flagged;
|
|
312
316
|
const found = Object.values(TARGETS).filter((t) => t.detect());
|
|
313
|
-
if (
|
|
317
|
+
if (interactive()) {
|
|
318
|
+
return askTargets({
|
|
319
|
+
title: "Where should Job Apply be installed?",
|
|
320
|
+
notes: (t) => (found.includes(t) ? " (found on this computer)" : ""),
|
|
321
|
+
defaultChoice: choiceFor(found),
|
|
322
|
+
verb: "installed",
|
|
323
|
+
});
|
|
324
|
+
}
|
|
314
325
|
// No terminal to ask in: fall back to the apps found here (both if none).
|
|
315
326
|
const targets = found.length ? found : Object.values(TARGETS);
|
|
316
327
|
log(`No app chosen; installing for ${targets.map((t) => t.label).join(" and ")}. Use --claude, --chatgpt or --all to choose.`);
|
|
317
328
|
return targets;
|
|
318
329
|
}
|
|
319
330
|
|
|
331
|
+
// Returns [] when there is nothing to remove.
|
|
332
|
+
async function pickUninstallTargets(values, opts) {
|
|
333
|
+
const flagged = flagTargets(values);
|
|
334
|
+
if (flagged.length) return flagged;
|
|
335
|
+
const statuses = new Map(Object.values(TARGETS).map((t) => [t, t.status(opts)]));
|
|
336
|
+
const installed = [...statuses].filter(([, s]) => s !== "not installed").map(([t]) => t);
|
|
337
|
+
if (installed.length === 0) {
|
|
338
|
+
log("Job Apply isn't installed in Claude Code or ChatGPT on this computer. Nothing to remove.");
|
|
339
|
+
return [];
|
|
340
|
+
}
|
|
341
|
+
if (!interactive()) return Object.values(TARGETS);
|
|
342
|
+
return askTargets({
|
|
343
|
+
title: "Remove Job Apply from which app?",
|
|
344
|
+
notes: (t) => ` (${statuses.get(t).replace(/ \(.*$/, "").replace(/ — .*$/, "")})`,
|
|
345
|
+
defaultChoice: choiceFor(installed),
|
|
346
|
+
verb: "removed",
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
320
350
|
export async function main(argv = process.argv.slice(2)) {
|
|
321
351
|
const { values, positionals } = parseArgs({
|
|
322
352
|
args: argv,
|
|
@@ -348,10 +378,13 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
348
378
|
}
|
|
349
379
|
log();
|
|
350
380
|
log(`Your résumé, profile and application history are stored locally in ~/Documents/Job Apply.`);
|
|
351
|
-
} else if (command === "uninstall") {
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
381
|
+
} else if (command === "uninstall" || command === "remove") {
|
|
382
|
+
const targets = await pickUninstallTargets(values, opts);
|
|
383
|
+
if (targets.length === 0) return;
|
|
384
|
+
for (const t of targets) t.uninstall(opts);
|
|
385
|
+
log();
|
|
386
|
+
log(`Your résumé, profile and history in ~/Documents/Job Apply were kept.`);
|
|
387
|
+
log(`To erase them too, delete that folder or ask the assistant to "clear my Job Apply profile" before uninstalling.`);
|
|
355
388
|
} else if (command === "status") {
|
|
356
389
|
for (const t of Object.values(TARGETS)) log(`${t.label.padEnd(24)} ${t.status(opts)}`);
|
|
357
390
|
const py = pythonCheck();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "job-apply-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Job Apply plugin for Claude Code and ChatGPT/Codex: prepare and submit job applications from a résumé and profile saved on your device.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -14,6 +14,14 @@
|
|
|
14
14
|
"resume"
|
|
15
15
|
],
|
|
16
16
|
"author": "Filipe Linemburger",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/filipelinemburger/job-apply.git"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/filipelinemburger/job-apply#readme",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/filipelinemburger/job-apply/issues"
|
|
24
|
+
},
|
|
17
25
|
"type": "module",
|
|
18
26
|
"bin": {
|
|
19
27
|
"job-apply-plugin": "bin/job-apply.js"
|
package/plugin/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "job-apply",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"description": "Prepare and submit individual job applications using a résumé and profile saved on your device.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"jobs",
|