open-plan-annotator 1.0.12 → 1.0.13

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.
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Interactive plan annotation plugin for Claude Code",
8
- "version": "1.0.12"
8
+ "version": "1.0.13"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "open-plan-annotator",
13
13
  "source": "./",
14
14
  "description": "Interactive plan annotation UI: review, strikethrough, and comment on Claude's plans before approving. Fully local, no external services.",
15
- "version": "1.0.12",
15
+ "version": "1.0.13",
16
16
  "author": {
17
17
  "name": "ndom91"
18
18
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "open-plan-annotator",
3
3
  "description": "Interactive plan annotation UI: review, strikethrough, and comment on Claude's plans before approving. Fully local, no external services.",
4
- "version": "1.0.12",
4
+ "version": "1.0.13",
5
5
  "author": {
6
6
  "name": "ndom91"
7
7
  },
@@ -4,6 +4,7 @@ import { execFileSync, spawn } from "node:child_process";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
+ import { resolveCliMode } from "../shared/cliMode.mjs";
7
8
 
8
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
10
  const binaryPath = path.join(__dirname, "open-plan-annotator-binary");
@@ -11,18 +12,21 @@ const installScript = path.join(__dirname, "..", "install.mjs");
11
12
  const VERSION = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8")).version;
12
13
 
13
14
  const arg = process.argv[2];
15
+ const cliMode = resolveCliMode(arg, { stdinIsTTY: process.stdin.isTTY === true });
14
16
 
15
- if (arg === "--version" || arg === "-v") {
17
+ if (cliMode === "version") {
16
18
  console.log(VERSION);
17
19
  process.exit(0);
18
20
  }
19
21
 
20
- if (arg === "--help" || arg === "-h") {
22
+ if (cliMode === "help") {
21
23
  console.log(`open-plan-annotator v${VERSION}
22
24
 
23
25
  Usage:
24
- open-plan-annotator Run as a Claude Code hook (reads stdin)
26
+ open-plan-annotator Show this help (interactive shell)
27
+ open-plan-annotator < event.json Run as a Claude Code hook (reads stdin)
25
28
  open-plan-annotator update Update the binary to the latest version
29
+ open-plan-annotator upgrade Alias for update
26
30
  open-plan-annotator --version Print version
27
31
  open-plan-annotator --help Show this help
28
32
 
@@ -30,12 +34,22 @@ https://github.com/ndom91/open-plan-annotator`);
30
34
  process.exit(0);
31
35
  }
32
36
 
37
+ if (cliMode === "unknown") {
38
+ console.error(`open-plan-annotator: unknown command \`${arg}\``);
39
+ console.error("Run `open-plan-annotator --help` for usage.");
40
+ process.exit(1);
41
+ }
42
+
33
43
  // Buffer stdin immediately so it's not lost if we need to download first.
34
44
  // Skip when stdin is a TTY (manual invocation) to avoid blocking forever.
35
45
  let stdinBuffer;
36
- try {
37
- stdinBuffer = process.stdin.isTTY ? Buffer.alloc(0) : fs.readFileSync(0);
38
- } catch {
46
+ if (cliMode === "hook") {
47
+ try {
48
+ stdinBuffer = process.stdin.isTTY ? Buffer.alloc(0) : fs.readFileSync(0);
49
+ } catch {
50
+ stdinBuffer = Buffer.alloc(0);
51
+ }
52
+ } else {
39
53
  stdinBuffer = Buffer.alloc(0);
40
54
  }
41
55
 
@@ -65,8 +79,8 @@ if (!fs.existsSync(binaryPath)) {
65
79
  justInstalled = true;
66
80
  }
67
81
 
68
- // Handle `open-plan-annotator update` subcommand
69
- if (process.argv[2] === "update") {
82
+ // Handle `open-plan-annotator update|upgrade` subcommand
83
+ if (cliMode === "update") {
70
84
  if (justInstalled) {
71
85
  console.log("Binary installed (v" + VERSION + ")");
72
86
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-plan-annotator",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "type": "module",
5
5
  "description": "Fully local plugin for interactive plan annotation from your Agentic assistants",
6
6
  "author": "ndom91",
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @typedef {"hook" | "update" | "help" | "version" | "unknown"} CliMode
3
+ */
4
+
5
+ /**
6
+ * @typedef {{ stdinIsTTY?: boolean }} CliModeOptions
7
+ */
8
+
9
+ /**
10
+ * @param {string | undefined} arg
11
+ * @param {CliModeOptions} [options]
12
+ * @returns {CliMode}
13
+ */
14
+ export function resolveCliMode(arg, options = {}) {
15
+ if (!arg) {
16
+ return options.stdinIsTTY ? "help" : "hook";
17
+ }
18
+
19
+ if (arg === "update" || arg === "upgrade") return "update";
20
+ if (arg === "--help" || arg === "-h") return "help";
21
+ if (arg === "--version" || arg === "-v") return "version";
22
+ return "unknown";
23
+ }
@@ -0,0 +1,31 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { resolveCliMode } from "./cliMode.mjs";
3
+
4
+ describe("resolveCliMode", () => {
5
+ test("returns help for no-arg interactive invocation", () => {
6
+ expect(resolveCliMode(undefined, { stdinIsTTY: true })).toBe("help");
7
+ });
8
+
9
+ test("returns hook for no-arg piped invocation", () => {
10
+ expect(resolveCliMode(undefined, { stdinIsTTY: false })).toBe("hook");
11
+ });
12
+
13
+ test("defaults no-arg invocation to hook mode", () => {
14
+ expect(resolveCliMode(undefined)).toBe("hook");
15
+ });
16
+
17
+ test("treats upgrade as update alias", () => {
18
+ expect(resolveCliMode("upgrade")).toBe("update");
19
+ });
20
+
21
+ test("recognizes help and version flags", () => {
22
+ expect(resolveCliMode("--help")).toBe("help");
23
+ expect(resolveCliMode("-h")).toBe("help");
24
+ expect(resolveCliMode("--version")).toBe("version");
25
+ expect(resolveCliMode("-v")).toBe("version");
26
+ });
27
+
28
+ test("marks unknown commands explicitly", () => {
29
+ expect(resolveCliMode("noop")).toBe("unknown");
30
+ });
31
+ });