diff --git a/electron/cli/args.test.ts b/electron/cli/args.test.ts index 5d52f2ee9a..0dca2edcff 100644 --- a/electron/cli/args.test.ts +++ b/electron/cli/args.test.ts @@ -302,4 +302,54 @@ describe("parseCliArgs", () => { expect(parse(["help"])).toMatchObject({ kind: "help" }); expect(parse(["--help"])).toMatchObject({ kind: "help" }); }); + + it("parses cursor import from a CSV next to a video", () => { + const cmd = parse([ + "cursor", + "import", + "--csv", + "mouse.csv", + "--clicks", + "clicks.txt", + "--video", + "take.mp4", + "--width", + "1280", + "--height", + "720", + "--json", + ]); + expect(cmd).toMatchObject({ + kind: "cursor-import", + csvPath: inCwd("mouse.csv"), + clicksPath: inCwd("clicks.txt"), + videoPath: inCwd("take.mp4"), + outputPath: null, + width: 1280, + height: 720, + clickHoldMs: 60, + json: true, + }); + }); + + it("parses cursor import with --output and no --video", () => { + expect( + parse(["cursor", "import", "--csv", "mouse.csv", "--output", "out.cursor.json"]), + ).toMatchObject({ + kind: "cursor-import", + csvPath: inCwd("mouse.csv"), + videoPath: null, + outputPath: inCwd("out.cursor.json"), + }); + }); + + it("rejects cursor import without a csv or an output target", () => { + expect(parse(["cursor"])).toMatchObject({ kind: "error" }); + expect(parse(["cursor", "import"])).toMatchObject({ kind: "error" }); + expect(parse(["cursor", "import", "--csv", "m.csv"])).toMatchObject({ + kind: "error", + message: expect.stringContaining("--video"), + }); + expect(parse(["cursor", "export"])).toMatchObject({ kind: "error" }); + }); }); diff --git a/electron/cli/args.ts b/electron/cli/args.ts index b2b50bd7b2..4cd22e8ae7 100644 --- a/electron/cli/args.ts +++ b/electron/cli/args.ts @@ -37,10 +37,22 @@ export interface CliMcpCommand { kind: "mcp"; } +export interface CliCursorImportCommand { + kind: "cursor-import"; + csvPath: string; + clicksPath: string | null; + videoPath: string | null; + outputPath: string | null; + width: number; + height: number; + clickHoldMs: number; +} + export type CliCommand = ( | CliRequest | CliInfoCommand | CliPackCommand + | CliCursorImportCommand | CliMcpCommand | CliHelpCommand | CliErrorCommand @@ -76,6 +88,7 @@ const SUBCOMMANDS = new Set([ "pack", "captions", "info", + "cursor", "mcp", "help", "--help", @@ -92,6 +105,7 @@ Usage: openscreen captions Transcribe (on-device Whisper) and turn captions on [--min-words <1-12>] [--max-words <1-12>] openscreen info [--json] Inspect a project file + openscreen cursor import [options] Write