overlord-cli 0.2607151850.0 → 0.2607161024.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.
@@ -1 +1 @@
1
- 0.3.2
1
+ 0.3.3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://antigravity.google/schemas/v1/plugin.json",
3
3
  "name": "overlord",
4
- "version": "0.3.2",
4
+ "version": "0.3.3",
5
5
  "description": "Chat-driven access to Overlord mission protocol workflows with hook-driven activity capture.",
6
6
  "author": {
7
7
  "name": "Cooperativ",
@@ -328,7 +328,7 @@ process.stdin.on('data', async chunk => {
328
328
  result: {
329
329
  protocolVersion: PROTOCOL_VERSION,
330
330
  capabilities: { tools: { listChanged: false } },
331
- serverInfo: { name: 'overlord-antigravity', version: '0.3.2' }
331
+ serverInfo: { name: 'overlord-antigravity', version: '0.3.3' }
332
332
  }
333
333
  });
334
334
  continue;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overlord",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Overlord mission protocol workflow for Claude Code — attach/update/ask/deliver, slash commands, and hook-driven activity capture.",
5
5
  "author": {
6
6
  "name": "Cooperativ",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overlord",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Chat-driven access to Overlord mission protocol workflows with hook-driven activity capture.",
5
5
  "author": {
6
6
  "name": "Cooperativ",
@@ -328,7 +328,7 @@ process.stdin.on('data', async chunk => {
328
328
  result: {
329
329
  protocolVersion: PROTOCOL_VERSION,
330
330
  capabilities: { tools: { listChanged: false } },
331
- serverInfo: { name: 'overlord-codex', version: '0.3.2' }
331
+ serverInfo: { name: 'overlord-codex', version: '0.3.3' }
332
332
  }
333
333
  });
334
334
  continue;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overlord",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Overlord mission protocol workflow for Cursor — attach/update/ask/deliver, slash commands, MCP bridge, and follow-up capture.",
5
5
  "author": {
6
6
  "name": "Cooperativ",
@@ -29,7 +29,7 @@ From an OpenOverlord checkout:
29
29
  ovld agent-setup cursor
30
30
  ```
31
31
 
32
- This copies managed plugin files to `~/.cursor/plugins/local/overlord`, merges a `beforeSubmitPrompt` hook into `~/.cursor/hooks.json`, and adds a `Shell(ovld protocol:*)` permission allow rule to `~/.cursor/settings.json` when missing.
32
+ This copies managed plugin files to `~/.cursor/plugins/local/overlord`, merges Overlord's prompt, permission, tool-result, and stop hooks into `~/.cursor/hooks.json`, and adds a `Shell(ovld protocol:*)` permission allow rule to `~/.cursor/settings.json` when missing. Existing hooks and settings are preserved.
33
33
 
34
34
  Re-run safely any time the connector contract version changes:
35
35
 
@@ -76,9 +76,14 @@ This connector is intentionally reviewable against the four connector layers in
76
76
  - `skills/overlord-mission/SKILL.md` — Cursor adapter template with a `<!-- @connector-core -->` marker; setup interpolates shared core content at install time.
77
77
  - `commands/*.md` — slash commands for session routing, objective discussion, mission creation, and work recording.
78
78
  - `hooks/overlord-user-prompt-submit.sh` — `beforeSubmitPrompt` follow-up capture through `ovld protocol hook-event`.
79
+ - `hooks/overlord-permission-request.sh` — observes `beforeShellExecution` and `beforeMCPExecution` through `ovld protocol permission-request`. It returns no allow/deny decision, leaving Cursor and user-installed hooks authoritative.
80
+ - `hooks/overlord-post-tool-use.sh` — records `postToolUse` file edits and shell-mediated changes for exact per-session delivery attribution.
81
+ - `hooks/overlord-stop.sh` — checks pending delivery through `ovld protocol hook-event`; when needed, it asks Cursor to continue once so the agent can finish delivery.
79
82
  - `rules/overlord-local.mdc` — always-on workflow rules for Cursor sessions.
80
83
  - `mcp.json` + `scripts/overlord-mcp.mjs` — MCP bridge to common `ovld protocol` operations.
81
84
  - `conformance-manifest.yaml` — connector conformance declaration for the Overlord contract.
82
85
  - `prompt-wrapper.md` — Cursor launch guidance.
83
86
 
84
87
  The shared Connector Core source lives at `connectors/core/overlord-mission`. `ovld agent-setup cursor` interpolates that core into the adapter skill template and installs core reference files so the runtime package is self-contained.
88
+
89
+ Cursor's generic `preToolUse` hook is intentionally not used for permission capture. Cursor currently documents that `ask` is not enforced for `preToolUse`; the narrower shell and MCP hooks expose the native permission-decision schema without changing the user's policy. Cursor also documents hook execution as fail-open by default, so Overlord telemetry failures do not strand the agent.
@@ -8,11 +8,17 @@ connector:
8
8
  agentIdentifier: cursor
9
9
  capabilities:
10
10
  - followUpHook
11
+ - permissionHook
12
+ - stopHook
13
+ - editHook
11
14
  - modelFlag
12
15
  - permissionRules
13
16
  - slashCommands
14
17
  hookTypes:
15
18
  - UserPromptSubmit
19
+ - PermissionRequest
20
+ - PostToolUse
21
+ - Stop
16
22
  installPath: "~/.cursor/plugins/local/overlord"
17
23
  managedFiles:
18
24
  - ".cursor-plugin/plugin.json"
@@ -27,6 +33,9 @@ connector:
27
33
  - "commands/record-work.md"
28
34
  - "commands/spawn.md"
29
35
  - "hooks/overlord-user-prompt-submit.sh"
36
+ - "hooks/overlord-permission-request.sh"
37
+ - "hooks/overlord-post-tool-use.sh"
38
+ - "hooks/overlord-stop.sh"
30
39
  - "mcp.json"
31
40
  - "prompt-wrapper.md"
32
41
  - "rules/overlord-local.mdc"
@@ -0,0 +1,25 @@
1
+ #!/bin/bash
2
+ # Overlord Cursor permission observation hook.
3
+ #
4
+ # Cursor invokes this script from beforeShellExecution and beforeMCPExecution,
5
+ # its native permission-decision points. The hook records the request through
6
+ # the Connector -> Protocol surface but intentionally returns no decision, so
7
+ # Cursor's own permissions and any other user hooks remain authoritative.
8
+
9
+ BODY=$(cat -)
10
+
11
+ if [ -n "${MISSION_ID:-}" ] && command -v ovld >/dev/null 2>&1; then
12
+ (
13
+ USER_TOKEN="${Overlord_USER_TOKEN:-${OVLD_USER_TOKEN:-}}"
14
+ if [ -n "$USER_TOKEN" ]; then
15
+ export Overlord_USER_TOKEN="$USER_TOKEN"
16
+ fi
17
+ printf '%s' "$BODY" | ovld protocol permission-request \
18
+ --mission-id "$MISSION_ID" \
19
+ --payload-file - \
20
+ >/dev/null 2>&1
21
+ ) &
22
+ disown
23
+ fi
24
+
25
+ exit 0
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+ # Overlord Cursor postToolUse hook.
3
+ # Records Cursor Write/Edit and Shell effects in the per-session touched-files
4
+ # log used by `ovld protocol deliver` for concurrent-work attribution.
5
+
6
+ BODY=$(cat -)
7
+ LOG_DIR="${HOME:-}/.ovld/logs"
8
+ LOG_FILE="${LOG_DIR}/cursor-post-tool-use-hook.log"
9
+
10
+ log_hook() {
11
+ mkdir -p "$LOG_DIR" 2>/dev/null || return 0
12
+ printf '%s [cursor-post-tool-use] %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$1" >>"$LOG_FILE" 2>/dev/null || true
13
+ }
14
+
15
+ if ! command -v ovld >/dev/null 2>&1; then
16
+ log_hook "ovld not on PATH; skipping"
17
+ exit 0
18
+ fi
19
+
20
+ RESULT=$(printf '%s' "$BODY" | ovld protocol record-touched 2>>"$LOG_FILE")
21
+ log_hook "record-touched: ${RESULT:-<no output>}"
22
+
23
+ exit 0
@@ -0,0 +1,73 @@
1
+ #!/bin/bash
2
+ # Overlord Cursor stop hook.
3
+ # Checks whether the attached mission still needs delivery and, at most once,
4
+ # asks Cursor to continue so the agent can deliver. It never delivers itself.
5
+
6
+ BODY=$(cat -)
7
+ LOG_DIR="${HOME:-}/.ovld/logs"
8
+ LOG_FILE="${LOG_DIR}/cursor-stop-hook.log"
9
+
10
+ log_hook() {
11
+ mkdir -p "$LOG_DIR" 2>/dev/null || return 0
12
+ printf '%s [cursor-stop] %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$1" >>"$LOG_FILE" 2>/dev/null || true
13
+ }
14
+
15
+ if [ -z "${MISSION_ID:-}" ] || ! command -v ovld >/dev/null 2>&1; then
16
+ log_hook "missing required mission or ovld, skipping"
17
+ printf '{}'
18
+ exit 0
19
+ fi
20
+
21
+ LOOP_COUNT=$(printf '%s' "$BODY" | python3 -c '
22
+ import json, sys
23
+ try:
24
+ value = json.load(sys.stdin).get("loop_count", 0)
25
+ print(value if isinstance(value, int) else 0)
26
+ except Exception:
27
+ print(0)
28
+ ' 2>/dev/null)
29
+
30
+ if [ "${LOOP_COUNT:-0}" -gt 0 ]; then
31
+ log_hook "automatic follow-up already used, skipping"
32
+ printf '{}'
33
+ exit 0
34
+ fi
35
+
36
+ RESPONSE_FILE=$(mktemp "${TMPDIR:-/tmp}/overlord-cursor-stop.XXXXXX")
37
+ USER_TOKEN="${Overlord_USER_TOKEN:-${OVLD_USER_TOKEN:-}}"
38
+ if [ -n "$USER_TOKEN" ]; then
39
+ export Overlord_USER_TOKEN="$USER_TOKEN"
40
+ fi
41
+
42
+ ovld protocol hook-event \
43
+ --hook-type Stop \
44
+ --mission-id "$MISSION_ID" \
45
+ >"$RESPONSE_FILE" 2>/dev/null
46
+ OVLD_EXIT=$?
47
+
48
+ if [ "$OVLD_EXIT" -eq 0 ]; then
49
+ python3 - "$RESPONSE_FILE" <<'PY'
50
+ import json, sys
51
+
52
+ response = {}
53
+ try:
54
+ with open(sys.argv[1]) as handle:
55
+ data = json.load(handle)
56
+ status = data.get("deliveryStatus") or {}
57
+ if status.get("needed"):
58
+ reason = status.get("reason") or "Pending Overlord delivery work detected."
59
+ response["followup_message"] = (
60
+ f"[Overlord] {reason} Complete the required verification and deliver the attached mission now."
61
+ )
62
+ except Exception:
63
+ pass
64
+
65
+ print(json.dumps(response, separators=(",", ":")))
66
+ PY
67
+ else
68
+ log_hook "hook-event failed exit=$OVLD_EXIT"
69
+ printf '{}'
70
+ fi
71
+
72
+ rm -f "$RESPONSE_FILE"
73
+ exit 0
@@ -328,7 +328,7 @@ process.stdin.on('data', async chunk => {
328
328
  result: {
329
329
  protocolVersion: PROTOCOL_VERSION,
330
330
  capabilities: { tools: { listChanged: false } },
331
- serverInfo: { name: 'overlord-cursor', version: '0.3.2' }
331
+ serverInfo: { name: 'overlord-cursor', version: '0.3.3' }
332
332
  }
333
333
  });
334
334
  continue;
@@ -10,6 +10,9 @@ description: Cursor adapter for the shared Overlord mission workflow.
10
10
  - Agent identifier: `cursor` for `ovld protocol create` and `ovld protocol prompt`.
11
11
  - Native commands: `/attach`, `/connect`, `/load`, `/create`, `/prompt`, `/discuss-objective`, `/add-objectives`, `/record-work`.
12
12
  - Follow-up capture: the installed `beforeSubmitPrompt` hook records ordinary post-delivery user messages. Do not manually publish `user_follow_up` unless the hook is unavailable.
13
+ - Permission capture: installed `beforeShellExecution` and `beforeMCPExecution` hooks publish permission activity through `ovld protocol` without overriding Cursor's own decision.
14
+ - Edit capture: the installed `postToolUse` hook records Cursor file and shell effects for exact delivery attribution.
15
+ - Stop hook: the installed `stop` hook may auto-submit one pending-delivery reminder but does not deliver for you.
13
16
  - MCP bridge: the installed `overlord` MCP server exposes the hosted-compatible `overlord_*` mission tool catalog backed by `ovld protocol`.
14
17
  - Authentication: use shared `ovld auth` credentials, Overlord-launched environment variables, or `Overlord_USER_TOKEN` / `OVLD_USER_TOKEN`.
15
18
 
@@ -99,6 +99,9 @@ Requirements:
99
99
 
100
100
  - Install local Cursor plugin/rules/commands.
101
101
  - Add `beforeSubmitPrompt` hook to record follow-ups.
102
+ - Map `beforeShellExecution` and `beforeMCPExecution` onto the canonical observational `PermissionRequest` hook without overriding Cursor's permission decision.
103
+ - Add `postToolUse` edit capture for file tools and shell-mediated changes.
104
+ - Add a bounded `stop` hook for pending-delivery reminders.
102
105
  - Add permission allow rules for protocol commands.
103
106
  - Launch with model flag where supported.
104
107
  - No thinking/effort flag required initially.
@@ -27,10 +27,10 @@ For each connector's `conformance-manifest.yaml`
27
27
  `componentType: connector`, valid `componentKey`, required `connector` block with
28
28
  `agentIdentifier` + `capabilities`.
29
29
  - Every `capabilities` value is in `approvedConnectorCapabilities`
30
- (`followUpHook`, `permissionHook`, `stopHook`, `nativeResume`, `modelFlag`,
30
+ (`followUpHook`, `permissionHook`, `stopHook`, `editHook`, `nativeResume`, `modelFlag`,
31
31
  `effortFlag`, `contextFilePrompt`, `permissionRules`, `slashCommands`).
32
32
  - Every `hookTypes` value is in `approvedHookTypes`
33
- (`UserPromptSubmit`, `PermissionRequest`, `Stop`).
33
+ (`UserPromptSubmit`, `PermissionRequest`, `PostToolUse`, `Stop`).
34
34
  - `contractVersion` is a known contract version.
35
35
  - `agentIdentifier` is a documented or namespaced connector identifier (open vocab).
36
36
 
@@ -80,6 +80,7 @@ properties:
80
80
  - followUpHook
81
81
  - permissionHook
82
82
  - stopHook
83
+ - editHook
83
84
  - nativeResume
84
85
  - modelFlag
85
86
  - effortFlag
@@ -95,6 +96,7 @@ properties:
95
96
  enum:
96
97
  - UserPromptSubmit
97
98
  - PermissionRequest
99
+ - PostToolUse
98
100
  - Stop
99
101
  uniqueItems: true
100
102
  managedFiles:
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
1
3
  // Overlord CLI bundle — generated by cli/scripts/build.mjs. Do not edit.
2
4
  var __create = Object.create;
3
5
  var __defProp = Object.defineProperty;
@@ -2421,18 +2423,56 @@ function configureCursorHarness({
2421
2423
  };
2422
2424
  const hookRoot = hooks.hooks;
2423
2425
  const hookEntries = hookRoot && typeof hookRoot === "object" && !Array.isArray(hookRoot) ? hookRoot : {};
2424
- const beforeSubmit = Array.isArray(hookEntries.beforeSubmitPrompt) ? [...hookEntries.beforeSubmitPrompt] : [];
2425
- const alreadyInstalled = beforeSubmit.some((entry) => {
2426
- if (!entry || typeof entry !== "object") return false;
2427
- const command = entry.command;
2428
- return typeof command === "string" && command.includes("overlord-user-prompt-submit");
2429
- });
2430
- if (!alreadyInstalled) {
2431
- beforeSubmit.push({ command: CURSOR_HOOK_COMMAND });
2432
- hookEntries.beforeSubmitPrompt = beforeSubmit;
2426
+ const mergeHook = ({
2427
+ event,
2428
+ command,
2429
+ marker,
2430
+ extra = {}
2431
+ }) => {
2432
+ const entries = Array.isArray(hookEntries[event]) ? [...hookEntries[event]] : [];
2433
+ const alreadyInstalled = entries.some((entry) => {
2434
+ if (!entry || typeof entry !== "object") return false;
2435
+ const installedCommand = entry.command;
2436
+ return typeof installedCommand === "string" && installedCommand.includes(marker);
2437
+ });
2438
+ if (alreadyInstalled) return false;
2439
+ entries.push({ command, ...extra });
2440
+ hookEntries[event] = entries;
2441
+ return true;
2442
+ };
2443
+ const installedHookEvents = [
2444
+ mergeHook({
2445
+ event: "beforeSubmitPrompt",
2446
+ command: CURSOR_HOOK_COMMANDS.beforeSubmitPrompt,
2447
+ marker: "overlord-user-prompt-submit"
2448
+ }) && "beforeSubmitPrompt",
2449
+ mergeHook({
2450
+ event: "beforeShellExecution",
2451
+ command: CURSOR_HOOK_COMMANDS.beforePermission,
2452
+ marker: "overlord-permission-request"
2453
+ }) && "beforeShellExecution",
2454
+ mergeHook({
2455
+ event: "beforeMCPExecution",
2456
+ command: CURSOR_HOOK_COMMANDS.beforePermission,
2457
+ marker: "overlord-permission-request"
2458
+ }) && "beforeMCPExecution",
2459
+ mergeHook({
2460
+ event: "postToolUse",
2461
+ command: CURSOR_HOOK_COMMANDS.postToolUse,
2462
+ marker: "overlord-post-tool-use",
2463
+ extra: { matcher: "Shell|Write|Edit|MultiEdit|NotebookEdit" }
2464
+ }) && "postToolUse",
2465
+ mergeHook({
2466
+ event: "stop",
2467
+ command: CURSOR_HOOK_COMMANDS.stop,
2468
+ marker: "overlord-stop",
2469
+ extra: { loop_limit: 1 }
2470
+ }) && "stop"
2471
+ ].filter((event) => Boolean(event));
2472
+ if (installedHookEvents.length > 0) {
2433
2473
  hooks.hooks = hookEntries;
2434
2474
  if (dryRun) {
2435
- warnings.push(`Would merge beforeSubmitPrompt hook into ${hooksPath}.`);
2475
+ warnings.push(`Would merge ${installedHookEvents.join(", ")} hooks into ${hooksPath}.`);
2436
2476
  } else {
2437
2477
  mkdirSync3(cursorDir, { recursive: true });
2438
2478
  writeFileSync3(hooksPath, `${JSON.stringify(hooks, null, 2)}
@@ -2863,7 +2903,7 @@ function inspectConnector({
2863
2903
  problems
2864
2904
  };
2865
2905
  }
2866
- var CURSOR_HOOK_COMMAND, CURSOR_PROTOCOL_PERMISSION, CODEX_PLUGIN_KEY, CODEX_RULES_START, CODEX_RULES_END, CLAUDE_MARKETPLACE_NAME, CLAUDE_PLUGIN_KEY;
2906
+ var CURSOR_HOOK_COMMANDS, CURSOR_PROTOCOL_PERMISSION, CODEX_PLUGIN_KEY, CODEX_RULES_START, CODEX_RULES_END, CLAUDE_MARKETPLACE_NAME, CLAUDE_PLUGIN_KEY;
2867
2907
  var init_connectors = __esm({
2868
2908
  "src/connectors.ts"() {
2869
2909
  "use strict";
@@ -2871,7 +2911,12 @@ var init_connectors = __esm({
2871
2911
  init_config();
2872
2912
  init_connector_core_render();
2873
2913
  init_errors();
2874
- CURSOR_HOOK_COMMAND = "plugins/local/overlord/hooks/overlord-user-prompt-submit.sh";
2914
+ CURSOR_HOOK_COMMANDS = {
2915
+ beforeSubmitPrompt: "plugins/local/overlord/hooks/overlord-user-prompt-submit.sh",
2916
+ beforePermission: "plugins/local/overlord/hooks/overlord-permission-request.sh",
2917
+ postToolUse: "plugins/local/overlord/hooks/overlord-post-tool-use.sh",
2918
+ stop: "plugins/local/overlord/hooks/overlord-stop.sh"
2919
+ };
2875
2920
  CURSOR_PROTOCOL_PERMISSION = "Shell(ovld protocol:*)";
2876
2921
  CODEX_PLUGIN_KEY = "overlord@overlord-local";
2877
2922
  CODEX_RULES_START = "# overlord:permissions:start";
@@ -15487,7 +15532,7 @@ function recordTouchedFromPayload({
15487
15532
  missionId = resolved.missionId;
15488
15533
  ambiguous = resolved.ambiguous;
15489
15534
  }
15490
- if (toolName === "Bash") {
15535
+ if (toolName === "Bash" || toolName === "Shell") {
15491
15536
  const { addedCount } = recordBashObservedChanges({ workingDirectory, missionId });
15492
15537
  return { recorded: true, missionId, ambiguous, files: addedCount };
15493
15538
  }
@@ -16618,7 +16663,17 @@ async function runProtocolCommand({
16618
16663
  if (subcommand === "deliver" && missionId) {
16619
16664
  clearCachedSessionKey({ missionId, workingDirectory });
16620
16665
  removeActiveSession({ workingDirectory, missionId });
16621
- const connectorInstallsEditHook = existsSync22(path26.join(os5.homedir(), ".claude"));
16666
+ const connectorInstallsEditHook = existsSync22(path26.join(os5.homedir(), ".claude")) || existsSync22(
16667
+ path26.join(
16668
+ os5.homedir(),
16669
+ ".cursor",
16670
+ "plugins",
16671
+ "local",
16672
+ "overlord",
16673
+ "hooks",
16674
+ "overlord-post-tool-use.sh"
16675
+ )
16676
+ );
16622
16677
  if (connectorInstallsEditHook && !hasTouchedFilesLog({ workingDirectory, missionId }) && readChangedFiles(workingDirectory).length > 0) {
16623
16678
  const warning = `[overlord] warning: no touched-files log found at deliver for mission ${missionId} in ${workingDirectory}, even though this connector installs a PostToolUse edit hook. Deliver is falling back to baseline-only attribution, which can misattribute concurrent sessions' edits. Check ~/.ovld/logs/post-tool-use-hook.log for why the hook did not record any touched files.`;
16624
16679
  console.error(warning);
@@ -17332,6 +17387,7 @@ var init_commands = __esm({
17332
17387
  "heartbeat",
17333
17388
  "ask",
17334
17389
  "deliver",
17390
+ "hook-event",
17335
17391
  "record-change-rationales"
17336
17392
  ]);
17337
17393
  }