keyfabe 0.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.
Files changed (59) hide show
  1. package/README.md +125 -0
  2. package/dist/commands/clone.d.ts +1 -0
  3. package/dist/commands/clone.js +66 -0
  4. package/dist/commands/clone.js.map +1 -0
  5. package/dist/commands/delete.d.ts +1 -0
  6. package/dist/commands/delete.js +13 -0
  7. package/dist/commands/delete.js.map +1 -0
  8. package/dist/commands/doctor.d.ts +1 -0
  9. package/dist/commands/doctor.js +73 -0
  10. package/dist/commands/doctor.js.map +1 -0
  11. package/dist/commands/export.d.ts +1 -0
  12. package/dist/commands/export.js +14 -0
  13. package/dist/commands/export.js.map +1 -0
  14. package/dist/commands/import.d.ts +1 -0
  15. package/dist/commands/import.js +39 -0
  16. package/dist/commands/import.js.map +1 -0
  17. package/dist/commands/list.d.ts +1 -0
  18. package/dist/commands/list.js +26 -0
  19. package/dist/commands/list.js.map +1 -0
  20. package/dist/commands/read.d.ts +1 -0
  21. package/dist/commands/read.js +41 -0
  22. package/dist/commands/read.js.map +1 -0
  23. package/dist/commands/rename.d.ts +1 -0
  24. package/dist/commands/rename.js +17 -0
  25. package/dist/commands/rename.js.map +1 -0
  26. package/dist/commands/setup.d.ts +1 -0
  27. package/dist/commands/setup.js +158 -0
  28. package/dist/commands/setup.js.map +1 -0
  29. package/dist/commands/show.d.ts +1 -0
  30. package/dist/commands/show.js +20 -0
  31. package/dist/commands/show.js.map +1 -0
  32. package/dist/commands/write.d.ts +1 -0
  33. package/dist/commands/write.js +22 -0
  34. package/dist/commands/write.js.map +1 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.js +58 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/lib/card-ops.d.ts +2 -0
  39. package/dist/lib/card-ops.js +89 -0
  40. package/dist/lib/card-ops.js.map +1 -0
  41. package/dist/lib/display.d.ts +7 -0
  42. package/dist/lib/display.js +20 -0
  43. package/dist/lib/display.js.map +1 -0
  44. package/dist/lib/firmware.d.ts +13 -0
  45. package/dist/lib/firmware.js +79 -0
  46. package/dist/lib/firmware.js.map +1 -0
  47. package/dist/lib/parsers.d.ts +25 -0
  48. package/dist/lib/parsers.js +58 -0
  49. package/dist/lib/parsers.js.map +1 -0
  50. package/dist/lib/pm3.d.ts +11 -0
  51. package/dist/lib/pm3.js +48 -0
  52. package/dist/lib/pm3.js.map +1 -0
  53. package/dist/lib/prompts.d.ts +4 -0
  54. package/dist/lib/prompts.js +27 -0
  55. package/dist/lib/prompts.js.map +1 -0
  56. package/dist/lib/store.d.ts +16 -0
  57. package/dist/lib/store.js +74 -0
  58. package/dist/lib/store.js.map +1 -0
  59. package/package.json +42 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function show(name: string): Promise<boolean>;
@@ -0,0 +1,20 @@
1
+ import chalk from "chalk";
2
+ import { printFobNotFound } from "../lib/display.js";
3
+ import { getFob } from "../lib/store.js";
4
+ export async function show(name) {
5
+ const fob = await getFob(name);
6
+ if (!fob) {
7
+ printFobNotFound(name);
8
+ return false;
9
+ }
10
+ console.log(chalk.bold(`\n Name: ${fob.name}`));
11
+ console.log(chalk.bold(` Type: ${fob.type}`));
12
+ console.log(chalk.bold(` ID: ${fob.id}`));
13
+ if (fob.encoding) {
14
+ console.log(chalk.bold(` Encoding: ${fob.encoding}`));
15
+ }
16
+ console.log(chalk.bold(` Saved: ${fob.savedAt.slice(0, 10)}`));
17
+ console.log();
18
+ return true;
19
+ }
20
+ //# sourceMappingURL=show.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAY;IACnC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACjD,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,IAAI,CAAC;AAChB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function write(name: string): Promise<boolean>;
@@ -0,0 +1,22 @@
1
+ import chalk from "chalk";
2
+ import { writeAndVerify } from "../lib/card-ops.js";
3
+ import { printFobNotFound } from "../lib/display.js";
4
+ import { waitForEnter } from "../lib/prompts.js";
5
+ import { getFob } from "../lib/store.js";
6
+ export async function write(name) {
7
+ const fob = await getFob(name);
8
+ if (!fob) {
9
+ printFobNotFound(name);
10
+ return false;
11
+ }
12
+ console.log(chalk.bold(`\nWriting "${fob.name}" (${fob.type} ${fob.id})\n`));
13
+ await waitForEnter("Place a blank T55x7 fob on the antenna.");
14
+ const success = await writeAndVerify({ type: fob.type, id: fob.id, encoding: fob.encoding });
15
+ if (success) {
16
+ console.log(chalk.green("\nWrite successful!\n"));
17
+ return true;
18
+ }
19
+ console.log(chalk.red("\nWrite failed.\n"));
20
+ return false;
21
+ }
22
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/commands/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAY;IACpC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7E,MAAM,YAAY,CAAC,yCAAyC,CAAC,CAAC;IAE9D,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE7F,IAAI,OAAO,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC5C,OAAO,KAAK,CAAC;AACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ import { program } from "commander";
3
+ import { clone } from "./commands/clone.js";
4
+ import { deleteFob } from "./commands/delete.js";
5
+ import { doctor } from "./commands/doctor.js";
6
+ import { exportFobs } from "./commands/export.js";
7
+ import { importFile } from "./commands/import.js";
8
+ import { list } from "./commands/list.js";
9
+ import { read } from "./commands/read.js";
10
+ import { rename } from "./commands/rename.js";
11
+ import { setup } from "./commands/setup.js";
12
+ import { show } from "./commands/show.js";
13
+ import { write } from "./commands/write.js";
14
+ function withExitCode(fn) {
15
+ return async (...args) => {
16
+ const ok = await fn(...args);
17
+ if (!ok)
18
+ process.exitCode = 1;
19
+ };
20
+ }
21
+ program.name("keyfabe").description("CLI tool for Proxmark3 keyfob cloning").version("0.1.0");
22
+ program
23
+ .command("doctor")
24
+ .description("Check device connection, firmware, and antenna health")
25
+ .action(withExitCode(doctor));
26
+ program.command("read").description("Read and identify a fob on the antenna").action(withExitCode(read));
27
+ program.command("clone").description("Interactive guided clone flow (read + write)").action(withExitCode(clone));
28
+ program
29
+ .command("write")
30
+ .description("Write a previously-saved identity to a blank fob")
31
+ .argument("<name>", "name of the saved fob identity")
32
+ .action(withExitCode(write));
33
+ program.command("list").description("List all saved fob identities").action(withExitCode(list));
34
+ program
35
+ .command("show")
36
+ .description("Show details of a saved fob identity")
37
+ .argument("<name>", "name of the saved fob identity")
38
+ .action(withExitCode(show));
39
+ program
40
+ .command("rename")
41
+ .description("Rename a saved fob identity")
42
+ .argument("<old-name>", "current name")
43
+ .argument("<new-name>", "new name")
44
+ .action(withExitCode(rename));
45
+ program
46
+ .command("delete")
47
+ .description("Delete a saved fob identity")
48
+ .argument("<name>", "name of the saved fob identity")
49
+ .action(withExitCode(deleteFob));
50
+ program.command("export").description("Export all saved fob identities as JSON").action(withExitCode(exportFobs));
51
+ program
52
+ .command("import")
53
+ .description("Import fob identities from a JSON file")
54
+ .argument("<file>", "path to JSON file")
55
+ .action(withExitCode(importFile));
56
+ program.command("setup").description("Flash Iceman firmware to a stock Proxmark3 Easy").action(withExitCode(setup));
57
+ program.parse();
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { type CardInfo } from "./parsers.js";
2
+ export declare function writeAndVerify(card: CardInfo): Promise<boolean>;
@@ -0,0 +1,89 @@
1
+ import ora from "ora";
2
+ import { parseCloneResult, parseLfSearch, parseT55xxDetect } from "./parsers.js";
3
+ import { Pm3Error, pm3Exec } from "./pm3.js";
4
+ function cloneCommand(card) {
5
+ switch (card.type) {
6
+ case "EM410x":
7
+ return `lf em 410x clone --id ${card.id}`;
8
+ case "HID Prox":
9
+ return `lf hid clone -r ${card.id}`;
10
+ default:
11
+ throw new Error(`Unsupported card type: ${card.type}`);
12
+ }
13
+ }
14
+ function verifyCommand(card) {
15
+ switch (card.type) {
16
+ case "EM410x":
17
+ return "lf em 410x reader";
18
+ case "HID Prox":
19
+ return "lf hid reader";
20
+ default:
21
+ return "lf search";
22
+ }
23
+ }
24
+ export async function writeAndVerify(card) {
25
+ // Detect T55x7
26
+ const detectSpinner = ora("Detecting writable card...").start();
27
+ try {
28
+ const { stdout } = await pm3Exec("lf t55xx detect");
29
+ const t55 = parseT55xxDetect(stdout);
30
+ if (!t55) {
31
+ detectSpinner.fail("Card is not a writable T55x7. Use a blank T55x7 fob.");
32
+ return false;
33
+ }
34
+ detectSpinner.succeed(`Writable card detected (${t55.chipType})`);
35
+ }
36
+ catch (err) {
37
+ if (err instanceof Pm3Error) {
38
+ detectSpinner.fail(err.message);
39
+ }
40
+ else {
41
+ detectSpinner.fail("Failed to detect writable card.");
42
+ }
43
+ return false;
44
+ }
45
+ // Clone
46
+ const cloneSpinner = ora("Writing card data...").start();
47
+ try {
48
+ const cmd = cloneCommand(card);
49
+ const { stdout } = await pm3Exec(cmd);
50
+ const result = parseCloneResult(stdout);
51
+ if (!result.success) {
52
+ cloneSpinner.fail("Write command did not confirm success.");
53
+ return false;
54
+ }
55
+ cloneSpinner.succeed("Card data written");
56
+ }
57
+ catch (err) {
58
+ if (err instanceof Pm3Error) {
59
+ cloneSpinner.fail(err.message);
60
+ }
61
+ else {
62
+ cloneSpinner.fail("Failed to write card data.");
63
+ }
64
+ return false;
65
+ }
66
+ // Verify
67
+ const verifySpinner = ora("Verifying readback...").start();
68
+ try {
69
+ const cmd = verifyCommand(card);
70
+ const { stdout } = await pm3Exec(cmd);
71
+ const readback = parseLfSearch(stdout);
72
+ if (readback && readback.id === card.id) {
73
+ verifySpinner.succeed("Verification passed — IDs match");
74
+ return true;
75
+ }
76
+ verifySpinner.fail(`Verification failed — readback ID ${readback?.id ?? "not found"} doesn't match ${card.id}. Try again.`);
77
+ return false;
78
+ }
79
+ catch (err) {
80
+ if (err instanceof Pm3Error) {
81
+ verifySpinner.fail(err.message);
82
+ }
83
+ else {
84
+ verifySpinner.fail("Verification readback failed.");
85
+ }
86
+ return false;
87
+ }
88
+ }
89
+ //# sourceMappingURL=card-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-ops.js","sourceRoot":"","sources":["../../src/lib/card-ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { CardInfo } from "./parsers.js";
2
+ export declare const LF_VOLTAGE_THRESHOLD = 15;
3
+ export declare const HF_VOLTAGE_THRESHOLD = 10;
4
+ export declare const BREW_INSTALL_CMD = "brew tap rfidresearchgroup/proxmark3 && brew install proxmark3";
5
+ export declare function printBrewInstall(): void;
6
+ export declare function printCardInfo(card: CardInfo): void;
7
+ export declare function printFobNotFound(name: string): void;
@@ -0,0 +1,20 @@
1
+ import chalk from "chalk";
2
+ export const LF_VOLTAGE_THRESHOLD = 15;
3
+ export const HF_VOLTAGE_THRESHOLD = 10;
4
+ export const BREW_INSTALL_CMD = "brew tap rfidresearchgroup/proxmark3 && brew install proxmark3";
5
+ export function printBrewInstall() {
6
+ console.log(chalk.yellow(" Install Proxmark3 client:"));
7
+ console.log(chalk.yellow(` ${BREW_INSTALL_CMD}`));
8
+ }
9
+ export function printCardInfo(card) {
10
+ console.log(chalk.bold(`\n Type: ${card.type}`));
11
+ console.log(chalk.bold(` ID: ${card.id}`));
12
+ if (card.encoding) {
13
+ console.log(chalk.bold(` Encoding: ${card.encoding}`));
14
+ }
15
+ console.log();
16
+ }
17
+ export function printFobNotFound(name) {
18
+ console.log(chalk.red(`\nNo saved fob named "${name}". Use \`keyfabe list\` to see saved fobs.\n`));
19
+ }
20
+ //# sourceMappingURL=display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/lib/display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,gEAAgE,CAAC;AAEjG,MAAM,UAAU,gBAAgB;IAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,gBAAgB,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAc;IACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAClD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,IAAI,8CAA8C,CAAC,CAAC,CAAC;AACxG,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface ExecResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ }
5
+ export declare function execCommand(cmd: string, args: string[], opts?: {
6
+ timeout?: number;
7
+ cwd?: string;
8
+ }): Promise<ExecResult>;
9
+ export declare function checkInstalled(binary: string): Promise<boolean>;
10
+ export declare function findBrewCache(): Promise<string>;
11
+ export declare function buildFirmware(sourceDir: string): Promise<void>;
12
+ export declare function flashFirmware(port: string, sourceDir: string): Promise<void>;
13
+ export declare function waitForDevice(timeoutMs?: number): Promise<string | null>;
@@ -0,0 +1,79 @@
1
+ import { execFile } from "node:child_process";
2
+ import { detectPort } from "./pm3.js";
3
+ const BUILD_FLAGS = [
4
+ "PLATFORM=PM3GENERIC",
5
+ "PLATFORM_SIZE=256",
6
+ "SKIP_HITAG=1",
7
+ "SKIP_LEGICRF=1",
8
+ "SKIP_EM4x50=1",
9
+ "SKIP_EM4x70=1",
10
+ "SKIP_ICLASS=1",
11
+ "SKIP_FELICA=1",
12
+ "SKIP_HFPLOT=1",
13
+ "SKIP_HFSNIFF=1",
14
+ "SKIP_NFCBARCODE=1",
15
+ "SKIP_ZX8211=1",
16
+ "SKIP_ISO15693=1",
17
+ "SKIP_ISO14443b=1",
18
+ ];
19
+ export async function execCommand(cmd, args, opts) {
20
+ return new Promise((resolve, reject) => {
21
+ execFile(cmd, args, {
22
+ timeout: opts?.timeout ?? 120_000,
23
+ cwd: opts?.cwd,
24
+ }, (error, stdout, stderr) => {
25
+ const out = stdout?.toString() ?? "";
26
+ const err = stderr?.toString() ?? "";
27
+ if (error) {
28
+ const e = new Error(`${cmd} failed: ${error.message}`);
29
+ e.stdout = out;
30
+ e.stderr = err;
31
+ reject(e);
32
+ return;
33
+ }
34
+ resolve({ stdout: out, stderr: err });
35
+ });
36
+ });
37
+ }
38
+ export async function checkInstalled(binary) {
39
+ try {
40
+ await execCommand("which", [binary], { timeout: 5_000 });
41
+ return true;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ export async function findBrewCache() {
48
+ const { stdout } = await execCommand("brew", ["--cache", "rfidresearchgroup/proxmark3/proxmark3"], {
49
+ timeout: 10_000,
50
+ });
51
+ const path = stdout.trim();
52
+ if (!path) {
53
+ throw new Error("Proxmark3 not installed via Homebrew.");
54
+ }
55
+ return path;
56
+ }
57
+ export async function buildFirmware(sourceDir) {
58
+ await execCommand("make", ["clean"], { cwd: sourceDir, timeout: 30_000 });
59
+ await execCommand("make", ["-j4", "bootrom", "fullimage", ...BUILD_FLAGS], { cwd: sourceDir, timeout: 120_000 });
60
+ }
61
+ export async function flashFirmware(port, sourceDir) {
62
+ const bootrom = `${sourceDir}/bootrom/obj/bootrom.elf`;
63
+ const fullimage = `${sourceDir}/armsrc/obj/fullimage.elf`;
64
+ await execCommand("proxmark3", [port, "--flash", "--unlock-bootloader", "--image", bootrom, "--image", fullimage], {
65
+ timeout: 60_000,
66
+ });
67
+ }
68
+ export async function waitForDevice(timeoutMs = 15_000) {
69
+ const start = Date.now();
70
+ const interval = 1_000;
71
+ while (Date.now() - start < timeoutMs) {
72
+ const port = await detectPort();
73
+ if (port)
74
+ return port;
75
+ await new Promise((resolve) => setTimeout(resolve, interval));
76
+ }
77
+ return null;
78
+ }
79
+ //# sourceMappingURL=firmware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firmware.js","sourceRoot":"","sources":["../../src/lib/firmware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface HwStatus {
2
+ connected: boolean;
3
+ firmwareVersion: string;
4
+ }
5
+ export interface HwTune {
6
+ lfVoltage: number;
7
+ hfVoltage: number;
8
+ }
9
+ export interface CardInfo {
10
+ type: string;
11
+ id: string;
12
+ encoding?: string;
13
+ }
14
+ export interface T55xxInfo {
15
+ chipType: string;
16
+ passwordSet: boolean;
17
+ }
18
+ export interface CloneResult {
19
+ success: boolean;
20
+ }
21
+ export declare function parseHwStatus(output: string): HwStatus;
22
+ export declare function parseHwTune(output: string): HwTune;
23
+ export declare function parseLfSearch(output: string): CardInfo | null;
24
+ export declare function parseT55xxDetect(output: string): T55xxInfo | null;
25
+ export declare function parseCloneResult(output: string): CloneResult;
@@ -0,0 +1,58 @@
1
+ export function parseHwStatus(output) {
2
+ const connected = !output.includes("cannot communicate") && !output.includes("ERROR");
3
+ const fwMatch = output.match(/firmware[^:]*:\s*(.+)/i) ??
4
+ output.match(/os:\s*(.+)/i) ??
5
+ output.match(/bootrom:\s*(.+)/i) ??
6
+ output.match(/mode\.+\s*(.+)/i);
7
+ const firmwareVersion = fwMatch?.[1]?.trim() ?? "unknown";
8
+ return { connected, firmwareVersion };
9
+ }
10
+ export function parseHwTune(output) {
11
+ const lfMatch = output.match(/125(?:\.00)?\s*kHz[^\d]*([\d.]+)\s*V/i);
12
+ const hfMatch = output.match(/13\.56\s*MHz[^\d]*([\d.]+)\s*V/i);
13
+ return {
14
+ lfVoltage: lfMatch ? parseFloat(lfMatch[1]) : 0,
15
+ hfVoltage: hfMatch ? parseFloat(hfMatch[1]) : 0,
16
+ };
17
+ }
18
+ export function parseLfSearch(output) {
19
+ // EM410x
20
+ const emMatch = output.match(/EM\s*410x\s*(?:ID|Tag ID)\s*[:\s]*([0-9A-Fa-f]{10})/i);
21
+ if (emMatch) {
22
+ const encodingMatch = output.match(/RF\/(\d+)/);
23
+ return {
24
+ type: "EM410x",
25
+ id: emMatch[1].toUpperCase(),
26
+ encoding: encodingMatch ? `RF/${encodingMatch[1]}` : undefined,
27
+ };
28
+ }
29
+ // HID Prox
30
+ const hidMatch = output.match(/HID\s*Prox\s*(?:TAG\s*)?ID\s*[:\s]*([0-9A-Fa-f]+)/i);
31
+ if (hidMatch) {
32
+ return {
33
+ type: "HID Prox",
34
+ id: hidMatch[1].toUpperCase(),
35
+ };
36
+ }
37
+ return null;
38
+ }
39
+ export function parseT55xxDetect(output) {
40
+ const chipMatch = output.match(/Chip\s*Type\s*[:\s]*(T55\w+)/i) ?? output.match(/(T55\w+)\s*(?:found|detected)/i);
41
+ if (!chipMatch) {
42
+ // Also check for general detection success
43
+ if (!output.includes("T55") && !output.includes("t55")) {
44
+ return null;
45
+ }
46
+ }
47
+ const passwordSet = /password\s*(?:is\s*)?set/i.test(output) || /password\s*[:\s]*yes/i.test(output);
48
+ return {
49
+ chipType: chipMatch?.[1] ?? "T55x7",
50
+ passwordSet,
51
+ };
52
+ }
53
+ export function parseCloneResult(output) {
54
+ const hasError = /error/i.test(output) && !/errorrate/i.test(output);
55
+ const hasDone = /done/i.test(output) || /written/i.test(output) || /cloned/i.test(output);
56
+ return { success: !hasError && hasDone };
57
+ }
58
+ //# sourceMappingURL=parsers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/lib/parsers.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,aAAa,CAAC,MAAc;IACxC,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACtF,MAAM,OAAO,GACT,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC;QACtC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC;QAC3B,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACpC,MAAM,eAAe,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAC1D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAChE,OAAO;QACH,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAClD,CAAC;AACN,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IACxC,SAAS;IACT,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;IACrF,IAAI,OAAO,EAAE,CAAC;QACV,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAChD,OAAO;YACH,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YAC5B,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;SACjE,CAAC;IACN,CAAC;IAED,WAAW;IACX,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACpF,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO;YACH,IAAI,EAAE,UAAU;YAChB,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;SAChC,CAAC;IACN,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAClH,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,2CAA2C;QAC3C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,2BAA2B,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAErG,OAAO;QACH,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO;QACnC,WAAW;KACd,CAAC;AACN,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1F,OAAO,EAAE,OAAO,EAAE,CAAC,QAAQ,IAAI,OAAO,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare class Pm3Error extends Error {
2
+ stdout: string;
3
+ stderr: string;
4
+ constructor(message: string, stdout: string, stderr: string);
5
+ }
6
+ export interface Pm3Result {
7
+ stdout: string;
8
+ stderr: string;
9
+ }
10
+ export declare function pm3Exec(command: string, timeout?: number): Promise<Pm3Result>;
11
+ export declare function detectPort(): Promise<string | null>;
@@ -0,0 +1,48 @@
1
+ import { execFile } from "node:child_process";
2
+ import { readdir } from "node:fs/promises";
3
+ const DEFAULT_TIMEOUT = 30_000;
4
+ export class Pm3Error extends Error {
5
+ stdout;
6
+ stderr;
7
+ constructor(message, stdout, stderr) {
8
+ super(message);
9
+ this.name = "Pm3Error";
10
+ this.stdout = stdout;
11
+ this.stderr = stderr;
12
+ }
13
+ }
14
+ export async function pm3Exec(command, timeout = DEFAULT_TIMEOUT) {
15
+ return new Promise((resolve, reject) => {
16
+ const _proc = execFile("pm3", ["-c", command], { timeout }, (error, stdout, stderr) => {
17
+ const out = stdout?.toString() ?? "";
18
+ const err = stderr?.toString() ?? "";
19
+ if (error) {
20
+ // Still return output on non-zero exit — pm3 often exits non-zero
21
+ // but only reject on actual execution failures (ENOENT, timeout)
22
+ if (error.code === "ENOENT") {
23
+ reject(new Pm3Error("pm3 command not found. Install Proxmark3 client: brew install proxmark3", out, err));
24
+ return;
25
+ }
26
+ if (error.killed) {
27
+ reject(new Pm3Error(`pm3 command timed out after ${timeout}ms`, out, err));
28
+ return;
29
+ }
30
+ // Non-zero exit but we got output — return it
31
+ resolve({ stdout: out, stderr: err });
32
+ return;
33
+ }
34
+ resolve({ stdout: out, stderr: err });
35
+ });
36
+ });
37
+ }
38
+ export async function detectPort() {
39
+ try {
40
+ const entries = await readdir("/dev");
41
+ const match = entries.find((e) => e.startsWith("tty.usbmodem"));
42
+ return match ? `/dev/${match}` : null;
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ //# sourceMappingURL=pm3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pm3.js","sourceRoot":"","sources":["../../src/lib/pm3.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,MAAM,eAAe,GAAG,MAAM,CAAC;AAE/B,MAAM,OAAO,QAAS,SAAQ,KAAK;IAC/B,MAAM,CAAS;IACf,MAAM,CAAS;IACf,YAAY,OAAe,EAAE,MAAc,EAAE,MAAc;QACvD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;CACJ;AAOD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAe,EAAE,OAAO,GAAG,eAAe;IACpE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAClF,MAAM,GAAG,GAAG,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YACrC,IAAI,KAAK,EAAE,CAAC;gBACR,kEAAkE;gBAClE,iEAAiE;gBACjE,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACrD,MAAM,CACF,IAAI,QAAQ,CACR,yEAAyE,EACzE,GAAG,EACH,GAAG,CACN,CACJ,CAAC;oBACF,OAAO;gBACX,CAAC;gBACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,QAAQ,CAAC,+BAA+B,OAAO,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;oBAC3E,OAAO;gBACX,CAAC;gBACD,8CAA8C;gBAC9C,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBACtC,OAAO;YACX,CAAC;YACD,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC5B,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;QAChE,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function prompt(message: string): Promise<string>;
2
+ export declare function confirm(message: string): Promise<boolean>;
3
+ export declare function waitForEnter(message: string): Promise<void>;
4
+ export declare function promptName(): Promise<string | null>;
@@ -0,0 +1,27 @@
1
+ import { stdin, stdout } from "node:process";
2
+ import { createInterface } from "node:readline/promises";
3
+ function createRl() {
4
+ return createInterface({ input: stdin, output: stdout });
5
+ }
6
+ export async function prompt(message) {
7
+ const rl = createRl();
8
+ try {
9
+ return await rl.question(message);
10
+ }
11
+ finally {
12
+ rl.close();
13
+ }
14
+ }
15
+ export async function confirm(message) {
16
+ const answer = await prompt(`${message} [y/N] `);
17
+ return answer.toLowerCase().startsWith("y");
18
+ }
19
+ export async function waitForEnter(message) {
20
+ await prompt(`${message} [Press Enter] `);
21
+ }
22
+ export async function promptName() {
23
+ const name = await prompt("Save as (name, or empty to skip): ");
24
+ const trimmed = name.trim();
25
+ return trimmed || null;
26
+ }
27
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/lib/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,SAAS,QAAQ;IACb,OAAO,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAe;IACxC,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,IAAI,CAAC;QACD,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;YAAS,CAAC;QACP,EAAE,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAe;IACzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,OAAO,SAAS,CAAC,CAAC;IACjD,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe;IAC9C,MAAM,MAAM,CAAC,GAAG,OAAO,iBAAiB,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC5B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,oCAAoC,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,OAAO,OAAO,IAAI,IAAI,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface Fob {
2
+ name: string;
3
+ type: string;
4
+ id: string;
5
+ encoding?: string;
6
+ savedAt: string;
7
+ }
8
+ export declare function loadFobs(): Promise<Fob[]>;
9
+ export declare function saveFob(fob: Fob): Promise<void>;
10
+ export declare function getFob(name: string): Promise<Fob | undefined>;
11
+ export declare function renameFob(oldName: string, newName: string): Promise<"ok" | "not-found" | "name-taken">;
12
+ export declare function importFobs(incoming: Fob[]): Promise<{
13
+ added: number;
14
+ updated: number;
15
+ }>;
16
+ export declare function removeFob(name: string): Promise<boolean>;