@scopebond/hook 0.3.0 → 0.5.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/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// scopebond-hook — govern a coding agent's tool calls against policy, in-path,\n// before they run, with a signed local receipt.\n//\n// scopebond-hook claude evaluate a Claude Code PreToolUse call (stdin JSON)\n// scopebond-hook cursor evaluate a Cursor hook event (stdin JSON)\n// scopebond-hook init [--cursor] [--no-install] scaffold keys + starter policy and configure the agent\n// scopebond-hook connect <url> <bundle.json> [--cursor]\n// enroll with a Cloud workspace and start exporting\n// scopebond-hook log [-n N] show the most recent local receipts\n// scopebond-hook verify verify every local receipt offline against the attester key\n// scopebond-hook test \"<shell command>\" show the decision for a command without recording it\n// scopebond-hook flush deliver any queued receipts to Cloud now\n//\n// Config dir: $SCOPEBOND_HOOK_DIR, else ./.scopebond\n// Fail-closed: any error denies the action with a repair message.\n\nimport { readFileSync, existsSync, mkdtempSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { execFileSync } from \"node:child_process\";\nimport type { CloudEnrollmentBundle } from \"@scopebond/gateway\";\nimport { verifyReceipt } from \"@scopebond/gateway\";\nimport { openReceiptStore, loadOrCreateAttester } from \"@scopebond/gateway/node\";\nimport { mapClaudeToolUse, mapCursorEvent, fillPushBranch } from \"./map.js\";\nimport { createHookRuntime } from \"./runtime.js\";\nimport { scaffold, harnessSnippet, installHarness } from \"./init.js\";\nimport { connectCloud, loadConnection, connectionPath } from \"./cloud.js\";\n\n/** The current git branch in `cwd` (best-effort). A bare `git push` pushes it, so\n * the runtime fills it in before evaluating; on failure the ref stays absent and\n * the starter policy fails closed. */\nfunction currentBranch(cwd: string): string | null {\n try {\n return execFileSync(\"git\", [\"-C\", cwd, \"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"], {\n encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim() || null;\n } catch { return null; }\n}\n\n/** Read an enrollment bundle from a file path, an inline base64 blob, or inline raw\n * JSON (the portal hands out a base64 blob so it is one clean argument). */\nfunction readBundleArg(bundleArg: string | undefined, stdin: () => string): CloudEnrollmentBundle {\n let text: string;\n if (!bundleArg) text = stdin();\n else if (existsSync(bundleArg)) text = readFileSync(bundleArg, \"utf8\");\n else if (bundleArg.trim().startsWith(\"{\")) text = bundleArg;\n else { try { text = Buffer.from(bundleArg, \"base64\").toString(\"utf8\"); } catch { text = bundleArg; } }\n return JSON.parse(text) as CloudEnrollmentBundle;\n}\n\nfunction configDir(): string {\n return process.env.SCOPEBOND_HOOK_DIR ?? join(process.cwd(), \".scopebond\");\n}\nfunction runtimePaths(dir: string) {\n const connection = loadConnection(dir);\n return {\n policyPath: join(dir, \"policy.json\"),\n keyPath: join(dir, \"agent.key\"),\n attesterPath: join(dir, \"attester.key\"),\n dbPath: join(dir, \"receipts.db\"),\n // Strict: deny (not just observe) tools with no taxonomy mapping.\n strict: process.argv.includes(\"--strict\") || process.env.SCOPEBOND_HOOK_STRICT === \"1\",\n // When connected, auto-export receipts. A short bounded flush keeps the hot path\n // fast; undelivered receipts persist in the durable outbox and flush next time\n // (or via `scopebond-hook flush`, e.g. on a session-end hook).\n ...(connection ? { cloud: { connection, flushTimeoutMs: Number(process.env.SCOPEBOND_HOOK_FLUSH_MS ?? 800) } } : {}),\n };\n}\nfunction readStdin(): string {\n try { return readFileSync(0, \"utf8\"); } catch { return \"\"; }\n}\n\nfunction denyClaude(reason: string): never {\n process.stdout.write(JSON.stringify({\n hookSpecificOutput: { hookEventName: \"PreToolUse\", permissionDecision: \"deny\", permissionDecisionReason: reason },\n }) + \"\\n\");\n process.stderr.write(`Scopebond: ${reason}\\n`);\n process.exit(2);\n}\n\nasync function runClaude(): Promise<void> {\n let input: Record<string, unknown>;\n try { input = JSON.parse(readStdin()); } catch { denyClaude(\"hook received invalid JSON on stdin\"); }\n try {\n const cwd = input?.cwd ? String(input.cwd) : process.cwd();\n const runtime = createHookRuntime(runtimePaths(configDir()));\n const decision = await runtime.evaluate(fillPushBranch(mapClaudeToolUse(input!), currentBranch(cwd)));\n await runtime.flush();\n if (decision.decision === \"deny\") denyClaude(decision.reason);\n // allow and not_evaluated both DEFER to Claude Code's own permission flow: the\n // hook records the receipt but never returns permissionDecision:\"allow\", which\n // would suppress the user's normal review. Scopebond blocks; it does not approve.\n process.exit(0);\n } catch (error) {\n denyClaude(`Scopebond hook failed closed: ${(error as Error).message}. Repair: run \\`scopebond-hook init\\`.`);\n }\n}\n\nasync function runCursor(): Promise<void> {\n let input: Record<string, unknown> = {};\n try { input = JSON.parse(readStdin()); } catch { /* fall through to fail-closed deny below */ }\n const event = String(input?.hook_event_name ?? input?.event ?? process.argv[3] ?? \"\");\n let permission: \"allow\" | \"deny\" | \"ask\" = \"deny\";\n let message = \"Scopebond hook failed closed\";\n try {\n const cwd = input?.cwd ? String(input.cwd) : process.cwd();\n const runtime = createHookRuntime(runtimePaths(configDir()));\n const decision = await runtime.evaluate(fillPushBranch(mapCursorEvent(event, input), currentBranch(cwd)));\n await runtime.flush();\n // Only an out-of-policy action is denied outright; an allowed or unevaluated\n // action defers to Cursor's own prompt (\"ask\"), never a silent auto-allow.\n permission = decision.decision === \"deny\" ? \"deny\" : \"ask\";\n message = decision.reason;\n } catch (error) {\n permission = \"deny\";\n message = `Scopebond hook failed closed: ${(error as Error).message}. Repair: run \\`scopebond-hook init\\`.`;\n }\n process.stdout.write(JSON.stringify({ permission, agentMessage: message }) + \"\\n\");\n process.exit(0);\n}\n\nfunction runInit(args: string[]): void {\n const harness = args.includes(\"--cursor\") ? \"cursor\" : \"claude\";\n const dir = configDir();\n const { agentKid, policyPath } = scaffold(dir, { force: args.includes(\"--force\") });\n console.log(`Scopebond hook enrolled in ${dir}`);\n console.log(` machine key ${agentKid}`);\n console.log(` policy ${policyPath} (starter — edit the limits)`);\n console.log(\"\");\n // Configure the agent automatically by default (idempotent), so there is no\n // hand-editing step; --no-install prints the snippet instead.\n if (!args.includes(\"--no-install\")) {\n const file = installHarness(harness);\n console.log(`✓ ${harness === \"cursor\" ? \"Cursor\" : \"Claude Code\"} configured in ${file}`);\n } else {\n console.log(`Add this to your ${harness === \"cursor\" ? \".cursor/hooks.json\" : \".claude/settings.json\"}:`);\n console.log(harnessSnippet(harness));\n }\n console.log(\"\");\n console.log(\"Next: run one command in the agent, then `scopebond-hook log` to see the receipt\");\n console.log(\"and `scopebond-hook verify` to check it offline. Try `scopebond-hook test \\\"rm -rf /\\\"`.\");\n console.log(\"To send receipts to a workspace: scopebond-hook connect <workspace-url> <enrollment>\");\n}\n\nfunction decisionOf(payload: Record<string, unknown>): string {\n const rr = String(payload.realtime_result ?? \"\");\n const state = String((payload.execution as Record<string, unknown> | undefined)?.state ?? \"\");\n if (state === \"observed_not_evaluated\") return \"not_evaluated\";\n if (rr === \"deny\") return state === \"cooperative_allow\" || state === \"executed\" ? \"monitor\" : \"deny\";\n return \"allow\";\n}\n\nfunction describeIntent(payload: Record<string, unknown>): string {\n const intent = (payload.intent ?? {}) as Record<string, unknown>;\n const p = (intent.params ?? {}) as Record<string, unknown>;\n const bits = intent.action_type === \"shell.exec\" ? String(p.program ?? \"\")\n : intent.action_type === \"git.push\" ? `${p.remote ?? \"\"} ${p.ref ?? \"\"}`.trim()\n : intent.action_type === \"file.write\" || intent.action_type === \"file.read\" ? String(p.path ?? \"\")\n : intent.action_type === \"mcp.tool.call\" ? `${p.server ?? \"\"}/${p.tool ?? \"\"}`\n : intent.action_type === \"net.fetch\" ? String(p.host ?? \"\") : \"\";\n return `${String(intent.action_type ?? \"?\")}${bits ? ` ${bits}` : \"\"}`;\n}\n\nasync function runLog(args: string[]): Promise<void> {\n const dir = configDir();\n const dbPath = join(dir, \"receipts.db\");\n if (!existsSync(dbPath)) { console.log(\"no receipts yet — run a command in the agent first.\"); process.exit(0); }\n const nIdx = args.indexOf(\"-n\");\n const n = nIdx >= 0 ? Math.max(1, Number(args[nIdx + 1]) || 20) : 20;\n const { store } = openReceiptStore({ db: dbPath });\n const all = await Promise.resolve(store.list());\n const recent = all.slice(-n);\n if (recent.length === 0) { console.log(\"no receipts yet.\"); process.exit(0); }\n for (const r of recent) {\n const p = r.payload as unknown as Record<string, unknown>;\n console.log(`${String(p.timestamp ?? \"\")} ${decisionOf(p).padEnd(13)} ${describeIntent(p)}`);\n }\n console.log(`\\n${recent.length} of ${all.length} receipt(s). Verify them: scopebond-hook verify`);\n}\n\nasync function runVerify(): Promise<void> {\n const dir = configDir();\n const dbPath = join(dir, \"receipts.db\");\n const attesterPath = join(dir, \"attester.key\");\n if (!existsSync(dbPath) || !existsSync(attesterPath)) { console.log(\"nothing to verify yet (no receipts or no attester key).\"); process.exit(0); }\n const { attester } = loadOrCreateAttester({ file: attesterPath });\n const { store } = openReceiptStore({ db: dbPath });\n const all = await Promise.resolve(store.list());\n let ok = 0;\n const bad: string[] = [];\n for (const r of all) {\n const result = verifyReceipt(r, attester.publicKeyPem) as unknown as Record<string, boolean>;\n if (result.valid) ok += 1;\n else {\n const failed = Object.entries(result).filter(([k, v]) => k.endsWith(\"_valid\") && v === false).map(([k]) => k);\n bad.push(`${String((r.payload as unknown as Record<string, unknown>).timestamp ?? \"\")}: ${failed.join(\", \") || \"invalid\"}`);\n }\n }\n console.log(`${ok}/${all.length} receipt(s) verify offline against ${attesterPath}.`);\n if (bad.length) { for (const b of bad) console.error(` ✗ ${b}`); process.exit(1); }\n process.exit(0);\n}\n\nasync function runTest(args: string[]): Promise<void> {\n const command = args.find((a) => !a.startsWith(\"-\"));\n if (!command) { console.error('usage: scopebond-hook test \"<shell command>\"'); process.exit(1); }\n const dir = configDir();\n if (!existsSync(join(dir, \"policy.json\"))) { console.error(\"no policy yet — run `scopebond-hook init` first.\"); process.exit(1); }\n // Evaluate against the real policy and keys, but a throwaway store, so `test`\n // never records a receipt or exports anything.\n const tmp = mkdtempSync(join(tmpdir(), \"sb-hook-test-\"));\n try {\n const runtime = createHookRuntime({\n policyPath: join(dir, \"policy.json\"), keyPath: join(dir, \"agent.key\"),\n attesterPath: join(dir, \"attester.key\"), dbPath: join(tmp, \"receipts.db\"),\n strict: process.argv.includes(\"--strict\"),\n });\n const mapped = fillPushBranch(mapClaudeToolUse({ tool_name: \"Bash\", tool_input: { command } }), currentBranch(process.cwd()));\n console.log(`command: ${command}`);\n for (const m of mapped) {\n const d = await runtime.evaluateOne(m);\n console.log(` ${describeIntent({ intent: m.intent }).padEnd(28)} → ${d.decision}${d.reason ? ` (${d.reason})` : \"\"}`);\n }\n const overall = await runtime.evaluate(mapped);\n console.log(`\\noverall: ${overall.decision}${overall.reason ? ` · ${overall.reason}` : \"\"}`);\n process.exit(overall.decision === \"deny\" ? 2 : 0);\n } finally {\n rmSync(tmp, { recursive: true, force: true });\n }\n}\n\nasync function runConnect(args: string[]): Promise<void> {\n const positional = args.filter((a) => !a.startsWith(\"--\"));\n const url = positional[0];\n const bundleArg = positional[1];\n const harness = args.includes(\"--cursor\") ? \"cursor\" : \"claude\";\n if (!url) {\n console.error(\"usage: scopebond-hook connect <workspace-url> <enrollment> [--cursor] [--no-install]\");\n process.exit(1);\n }\n const dir = configDir();\n // One command sets everything up: scaffold the key, attester and starter policy if\n // they do not exist, then enroll and persist the scoped machine credential. The\n // enrollment can be a file, an inline base64 blob (what the portal hands out) or\n // raw JSON — the user never has to save or open a JSON file.\n scaffold(dir, {});\n let bundle: CloudEnrollmentBundle;\n try { bundle = readBundleArg(bundleArg, readStdin); }\n catch { console.error(\"could not read the enrollment (expected a file, inline blob, or JSON on stdin)\"); process.exit(1); }\n try {\n const c = await connectCloud(dir, url, bundle);\n console.log(`✓ Connected to ${c.url}`);\n // Configure the agent automatically (merges into the existing config), unless the\n // caller opts out. This removes the \"paste this snippet\" step.\n if (!args.includes(\"--no-install\")) {\n const file = installHarness(harness);\n console.log(`✓ ${harness === \"cursor\" ? \"Cursor\" : \"Claude Code\"} configured in ${file}`);\n } else {\n console.log(`Add this to your ${harness === \"cursor\" ? \".cursor/hooks.json\" : \".claude/settings.json\"}:`);\n console.log(harnessSnippet(harness));\n }\n console.log(\"\");\n console.log(\"Run your agent — the first action appears in your workspace within seconds.\");\n } catch (error) {\n console.error(`connect failed: ${(error as Error).message}`);\n process.exit(1);\n }\n}\n\nasync function runFlush(): Promise<void> {\n const dir = configDir();\n if (!loadConnection(dir)) { console.error(\"not connected to a workspace; run `scopebond-hook connect` first\"); process.exit(1); }\n const runtime = createHookRuntime(runtimePaths(dir));\n await runtime.exporter?.flush();\n const status = runtime.exporter?.status();\n console.log(`flushed; ${status?.pending ?? 0} receipt(s) still pending${status?.lastError ? ` (last error: ${status.lastError})` : \"\"}`);\n process.exit(status && status.pending > 0 ? 1 : 0);\n}\n\nconst [cmd, ...rest] = process.argv.slice(2);\nif (cmd === \"claude\") { await runClaude(); }\nelse if (cmd === \"cursor\") { await runCursor(); }\nelse if (cmd === \"init\") { runInit(rest); }\nelse if (cmd === \"connect\") { await runConnect(rest); }\nelse if (cmd === \"log\") { await runLog(rest); }\nelse if (cmd === \"verify\") { await runVerify(); }\nelse if (cmd === \"test\") { await runTest(rest); }\nelse if (cmd === \"flush\") { await runFlush(); }\nelse {\n console.error(\"usage: scopebond-hook <claude|cursor|init|connect|log|verify|test|flush> [--cursor] [--force] [--strict] [--no-install]\");\n process.exit(1);\n}\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// scopebond-hook — govern a coding agent's tool calls against policy, in-path,\n// before they run, with a signed local receipt.\n//\n// scopebond-hook claude evaluate a Claude Code PreToolUse call (stdin JSON)\n// scopebond-hook cursor evaluate a Cursor hook event (stdin JSON)\n// scopebond-hook codex evaluate a Codex PreToolUse call (stdin JSON)\n// scopebond-hook init [--cursor|--codex] [--no-install]\n// scopebond-hook connect <url> <bundle.json> [--cursor|--codex]\n// enroll with a Cloud workspace and start exporting\n// scopebond-hook log [-n N] show the most recent local receipts\n// scopebond-hook verify verify every local receipt offline against the attester key\n// scopebond-hook test \"<shell command>\" show the decision for a command without recording it\n// scopebond-hook flush deliver any queued receipts to Cloud now\n//\n// Config dir: $SCOPEBOND_HOOK_DIR, else ./.scopebond\n// Fail-closed: any error denies the action with a repair message.\n\nimport { readFileSync, existsSync, mkdtempSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { execFileSync } from \"node:child_process\";\nimport type { CloudEnrollmentBundle } from \"@scopebond/gateway\";\nimport { verifyReceipt } from \"@scopebond/gateway\";\nimport { openReceiptStore, loadOrCreateAttester } from \"@scopebond/gateway/node\";\nimport { mapClaudeToolUse, mapCodexToolUse, mapCursorEvent, fillPushBranch, type Mapped } from \"./map.js\";\nimport { createHookRuntime } from \"./runtime.js\";\nimport { scaffold, harnessSnippet, installHarness } from \"./init.js\";\nimport {\n userHome, userHarnessFile, resolveConfigDir, writeHarnessConfig, removeHarnessConfig,\n cursorDetected, codexDetected, absoluteHookCommand, isHarnessConfigured, purgeHome, type Harness,\n} from \"./install.js\";\nimport { connectCloud, loadConnection, connectionPath } from \"./cloud.js\";\nimport { cliCommand, hookVersion } from \"./version.js\";\nimport { fileURLToPath } from \"node:url\";\n\n/** The current git branch in `cwd` (best-effort). A bare `git push` pushes it, so\n * the runtime fills it in before evaluating; on failure the ref stays absent and\n * the starter policy fails closed. */\nfunction currentBranch(cwd: string): string | null {\n try {\n return execFileSync(\"git\", [\"-C\", cwd, \"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"], {\n encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim() || null;\n } catch { return null; }\n}\n\n/** Read an enrollment bundle from a file path, an inline base64 blob, or inline raw\n * JSON (the portal hands out a base64 blob so it is one clean argument). */\nfunction readBundleArg(bundleArg: string | undefined, stdin: () => string): CloudEnrollmentBundle {\n let text: string;\n if (!bundleArg) text = stdin();\n else if (existsSync(bundleArg)) text = readFileSync(bundleArg, \"utf8\");\n else if (bundleArg.trim().startsWith(\"{\")) text = bundleArg;\n else { try { text = Buffer.from(bundleArg, \"base64\").toString(\"utf8\"); } catch { text = bundleArg; } }\n return JSON.parse(text) as CloudEnrollmentBundle;\n}\n\nfunction configDir(): string {\n return process.env.SCOPEBOND_HOOK_DIR ?? join(process.cwd(), \".scopebond\");\n}\nfunction runtimePaths(dir: string) {\n const connection = loadConnection(dir);\n return {\n policyPath: join(dir, \"policy.json\"),\n keyPath: join(dir, \"agent.key\"),\n attesterPath: join(dir, \"attester.key\"),\n dbPath: join(dir, \"receipts.db\"),\n // Strict: deny (not just observe) tools with no taxonomy mapping.\n strict: process.argv.includes(\"--strict\") || process.env.SCOPEBOND_HOOK_STRICT === \"1\",\n // When connected, auto-export receipts. A short bounded flush keeps the hot path\n // fast; undelivered receipts persist in the durable outbox and flush next time\n // (or via `scopebond-hook flush`, e.g. on a session-end hook).\n ...(connection ? { cloud: { connection, flushTimeoutMs: Number(process.env.SCOPEBOND_HOOK_FLUSH_MS ?? 800) } } : {}),\n };\n}\nfunction readStdin(): string {\n try { return readFileSync(0, \"utf8\"); } catch { return \"\"; }\n}\n\nfunction denyClaude(reason: string): never {\n process.stdout.write(JSON.stringify({\n hookSpecificOutput: { hookEventName: \"PreToolUse\", permissionDecision: \"deny\", permissionDecisionReason: reason },\n }) + \"\\n\");\n process.stderr.write(`Scopebond: ${reason}\\n`);\n process.exit(2);\n}\n\n/** Codex accepts the structured deny response on a successful hook exit. Keeping\n * exit 0 lets its UI show a completed policy check instead of a failed hook while\n * still preventing the tool call. */\nfunction denyCodex(reason: string): never {\n process.stdout.write(JSON.stringify({\n hookSpecificOutput: { hookEventName: \"PreToolUse\", permissionDecision: \"deny\", permissionDecisionReason: reason },\n }) + \"\\n\");\n process.exit(0);\n}\n\nconst harnessName = (harness: Harness): string => harness === \"claude\" ? \"Claude Code\" : harness === \"cursor\" ? \"Cursor\" : \"Codex\";\nconst harnessFileName = (harness: Harness): string => harness === \"claude\" ? \".claude/settings.json\" : harness === \"cursor\" ? \".cursor/hooks.json\" : \".codex/hooks.json\";\nconst selectedHarness = (args: string[]): Harness => args.includes(\"--codex\") ? \"codex\" : args.includes(\"--cursor\") ? \"cursor\" : \"claude\";\nconst codexTrustStep = \"Open Codex, run `/hooks`, review Scopebond, and choose Trust. Then start a new task.\";\n\nasync function runPreToolUse(mapper: (input: Record<string, unknown>) => Mapped[], deny: (reason: string) => never = denyClaude): Promise<void> {\n let input: Record<string, unknown>;\n try { input = JSON.parse(readStdin()); } catch { deny(\"hook received invalid JSON on stdin\"); }\n try {\n const cwd = input?.cwd ? String(input.cwd) : process.cwd();\n const runtime = createHookRuntime(runtimePaths(resolveConfigDir(cwd)));\n const decision = await runtime.evaluate(fillPushBranch(mapper(input!), currentBranch(cwd)));\n await runtime.flush();\n if (decision.decision === \"deny\") deny(decision.reason);\n // Stay silent on allow/not_evaluated so the coding agent's normal permission\n // flow remains in charge. Scopebond blocks; it never silently approves.\n process.exit(0);\n } catch (error) {\n deny(`Scopebond hook failed closed: ${(error as Error).message}. Repair: run \\`${cliCommand(\"init\")}\\`.`);\n }\n}\n\nasync function runClaude(): Promise<void> {\n await runPreToolUse(mapClaudeToolUse);\n}\n\nasync function runCodex(): Promise<void> {\n await runPreToolUse(mapCodexToolUse, denyCodex);\n}\n\nasync function runCursor(): Promise<void> {\n let input: Record<string, unknown> = {};\n try { input = JSON.parse(readStdin()); } catch { /* fall through to fail-closed deny below */ }\n const event = String(input?.hook_event_name ?? input?.event ?? process.argv[3] ?? \"\");\n let permission: \"allow\" | \"deny\" | \"ask\" = \"deny\";\n let message = \"Scopebond hook failed closed\";\n try {\n const cwd = input?.cwd ? String(input.cwd) : process.cwd();\n const runtime = createHookRuntime(runtimePaths(resolveConfigDir(cwd)));\n const decision = await runtime.evaluate(fillPushBranch(mapCursorEvent(event, input), currentBranch(cwd)));\n await runtime.flush();\n // Only an out-of-policy action is denied outright; an allowed or unevaluated\n // action defers to Cursor's own prompt (\"ask\"), never a silent auto-allow.\n permission = decision.decision === \"deny\" ? \"deny\" : \"ask\";\n message = decision.reason;\n } catch (error) {\n permission = \"deny\";\n message = `Scopebond hook failed closed: ${(error as Error).message}. Repair: run \\`${cliCommand(\"init\")}\\`.`;\n }\n process.stdout.write(JSON.stringify({ permission, agentMessage: message }) + \"\\n\");\n process.exit(0);\n}\n\nfunction runInit(args: string[]): void {\n const harness = selectedHarness(args);\n const dir = configDir();\n const { agentKid, policyPath } = scaffold(dir, { force: args.includes(\"--force\") });\n console.log(`Scopebond hook enrolled in ${dir}`);\n console.log(` machine key ${agentKid}`);\n console.log(` policy ${policyPath} (starter — edit the limits)`);\n console.log(\"\");\n // Configure the agent automatically by default (idempotent), so there is no\n // hand-editing step; --no-install prints the snippet instead.\n if (!args.includes(\"--no-install\")) {\n const file = installHarness(harness);\n console.log(`✓ ${harnessName(harness)} configured in ${file}`);\n if (harness === \"codex\") console.log(`\\nOne last step: ${codexTrustStep}`);\n } else {\n console.log(`Add this to your ${harnessFileName(harness)}:`);\n console.log(harnessSnippet(harness));\n }\n console.log(\"\");\n // Print the runnable `npx` form: after `npx @scopebond/hook init` there is no\n // `scopebond-hook` binary on PATH, so a bare `scopebond-hook log` would fail.\n console.log(`Next: run one command in the agent, then \\`${cliCommand(\"log\")}\\` to see the receipt`);\n console.log(`and \\`${cliCommand(\"verify\")}\\` to check it offline. Try \\`${cliCommand('test \"rm -rf /\"')}\\`.`);\n console.log(`To send receipts to a workspace: ${cliCommand(\"connect <workspace-url> <enrollment>\")}`);\n}\n\nfunction decisionOf(payload: Record<string, unknown>): string {\n const rr = String(payload.realtime_result ?? \"\");\n const state = String((payload.execution as Record<string, unknown> | undefined)?.state ?? \"\");\n if (state === \"observed_not_evaluated\") return \"not_evaluated\";\n if (rr === \"deny\") return state === \"cooperative_allow\" || state === \"executed\" ? \"monitor\" : \"deny\";\n return \"allow\";\n}\n\nfunction describeIntent(payload: Record<string, unknown>): string {\n const intent = (payload.intent ?? {}) as Record<string, unknown>;\n const p = (intent.params ?? {}) as Record<string, unknown>;\n const bits = intent.action_type === \"shell.exec\" ? String(p.program ?? \"\")\n : intent.action_type === \"git.push\" ? `${p.remote ?? \"\"} ${p.ref ?? \"\"}`.trim()\n : intent.action_type === \"file.write\" || intent.action_type === \"file.read\" ? String(p.path ?? \"\")\n : intent.action_type === \"mcp.tool.call\" ? `${p.server ?? \"\"}/${p.tool ?? \"\"}`\n : intent.action_type === \"net.fetch\" ? String(p.host ?? \"\") : \"\";\n return `${String(intent.action_type ?? \"?\")}${bits ? ` ${bits}` : \"\"}`;\n}\n\nasync function runLog(args: string[]): Promise<void> {\n const dir = resolveConfigDir(process.cwd());\n const dbPath = join(dir, \"receipts.db\");\n if (!existsSync(dbPath)) { console.log(\"no receipts yet — run a command in the agent first.\"); process.exit(0); }\n const nIdx = args.indexOf(\"-n\");\n const n = nIdx >= 0 ? Math.max(1, Number(args[nIdx + 1]) || 20) : 20;\n const { store } = openReceiptStore({ db: dbPath });\n const all = await Promise.resolve(store.list());\n const recent = all.slice(-n);\n if (recent.length === 0) { console.log(\"no receipts yet.\"); process.exit(0); }\n for (const r of recent) {\n const p = r.payload as unknown as Record<string, unknown>;\n console.log(`${String(p.timestamp ?? \"\")} ${decisionOf(p).padEnd(13)} ${describeIntent(p)}`);\n }\n console.log(`\\n${recent.length} of ${all.length} receipt(s). Verify them: ${cliCommand(\"verify\")}`);\n}\n\nasync function runVerify(): Promise<void> {\n const dir = resolveConfigDir(process.cwd());\n const dbPath = join(dir, \"receipts.db\");\n const attesterPath = join(dir, \"attester.key\");\n if (!existsSync(dbPath) || !existsSync(attesterPath)) { console.log(\"nothing to verify yet (no receipts or no attester key).\"); process.exit(0); }\n const { attester } = loadOrCreateAttester({ file: attesterPath });\n const { store } = openReceiptStore({ db: dbPath });\n const all = await Promise.resolve(store.list());\n let ok = 0;\n const bad: string[] = [];\n for (const r of all) {\n const result = verifyReceipt(r, attester.publicKeyPem) as unknown as Record<string, boolean>;\n if (result.valid) ok += 1;\n else {\n const failed = Object.entries(result).filter(([k, v]) => k.endsWith(\"_valid\") && v === false).map(([k]) => k);\n bad.push(`${String((r.payload as unknown as Record<string, unknown>).timestamp ?? \"\")}: ${failed.join(\", \") || \"invalid\"}`);\n }\n }\n console.log(`${ok}/${all.length} receipt(s) verify offline against ${attesterPath}.`);\n if (bad.length) { for (const b of bad) console.error(` ✗ ${b}`); process.exit(1); }\n process.exit(0);\n}\n\nasync function runTest(args: string[]): Promise<void> {\n const command = args.find((a) => !a.startsWith(\"-\"));\n if (!command) { console.error('usage: scopebond-hook test \"<shell command>\"'); process.exit(1); }\n const dir = resolveConfigDir(process.cwd());\n if (!existsSync(join(dir, \"policy.json\"))) { console.error(\"no policy yet — run `scopebond-hook init` first.\"); process.exit(1); }\n // Evaluate against the real policy and keys, but a throwaway store, so `test`\n // never records a receipt or exports anything.\n const tmp = mkdtempSync(join(tmpdir(), \"sb-hook-test-\"));\n try {\n const runtime = createHookRuntime({\n policyPath: join(dir, \"policy.json\"), keyPath: join(dir, \"agent.key\"),\n attesterPath: join(dir, \"attester.key\"), dbPath: join(tmp, \"receipts.db\"),\n strict: process.argv.includes(\"--strict\"),\n });\n const mapped = fillPushBranch(mapClaudeToolUse({ tool_name: \"Bash\", tool_input: { command } }), currentBranch(process.cwd()));\n console.log(`command: ${command}`);\n for (const m of mapped) {\n const d = await runtime.evaluateOne(m);\n console.log(` ${describeIntent({ intent: m.intent }).padEnd(28)} → ${d.decision}${d.reason ? ` (${d.reason})` : \"\"}`);\n }\n const overall = await runtime.evaluate(mapped);\n console.log(`\\noverall: ${overall.decision}${overall.reason ? ` · ${overall.reason}` : \"\"}`);\n process.exit(overall.decision === \"deny\" ? 2 : 0);\n } finally {\n rmSync(tmp, { recursive: true, force: true });\n }\n}\n\nasync function runConnect(args: string[]): Promise<void> {\n const positional = args.filter((a) => !a.startsWith(\"--\"));\n const url = positional[0];\n const bundleArg = positional[1];\n const harness = selectedHarness(args);\n if (!url) {\n console.error(\"usage: scopebond-hook connect <workspace-url> <enrollment> [--claude|--cursor|--codex] [--no-install]\");\n process.exit(1);\n }\n const dir = configDir();\n // One command sets everything up: scaffold the key, attester and starter policy if\n // they do not exist, then enroll and persist the scoped machine credential. The\n // enrollment can be a file, an inline base64 blob (what the portal hands out) or\n // raw JSON — the user never has to save or open a JSON file.\n scaffold(dir, {});\n let bundle: CloudEnrollmentBundle;\n try { bundle = readBundleArg(bundleArg, readStdin); }\n catch { console.error(\"could not read the enrollment (expected a file, inline blob, or JSON on stdin)\"); process.exit(1); }\n try {\n const c = await connectCloud(dir, url, bundle);\n console.log(`✓ Connected to ${c.url}`);\n // Configure the agent automatically (merges into the existing config), unless the\n // caller opts out. This removes the \"paste this snippet\" step.\n if (!args.includes(\"--no-install\")) {\n const file = installHarness(harness);\n console.log(`✓ ${harnessName(harness)} configured in ${file}`);\n if (harness === \"codex\") console.log(`\\nOne last step: ${codexTrustStep}`);\n } else {\n console.log(`Add this to your ${harnessFileName(harness)}:`);\n console.log(harnessSnippet(harness));\n }\n console.log(\"\");\n console.log(\"Run your agent — the first action appears in your workspace within seconds.\");\n } catch (error) {\n console.error(`connect failed: ${(error as Error).message}`);\n process.exit(1);\n }\n}\n\nasync function runFlush(): Promise<void> {\n const dir = resolveConfigDir(process.cwd());\n if (!loadConnection(dir)) { console.error(\"not connected to a workspace; run `scopebond-hook connect` first\"); process.exit(1); }\n const runtime = createHookRuntime(runtimePaths(dir));\n await runtime.exporter?.flush();\n const status = runtime.exporter?.status();\n runtime.exporter?.stop();\n console.log(`flushed; ${status?.pending ?? 0} receipt(s) still pending${status?.lastError ? ` (last error: ${status.lastError})` : \"\"}`);\n // Let pending HTTP handles close normally (forced exit can abort on Windows).\n process.exitCode = status && status.pending > 0 ? 1 : 0;\n}\n\n/** The absolute path to this CLI file, for registering the hook by absolute path. */\nfunction cliPath(): string {\n return fileURLToPath(import.meta.url);\n}\n\n/** `install` — the once-per-machine, user-level install (SB112). Scaffolds the\n * user home and registers the hook by absolute path in the user-level agent config,\n * so every project a developer opens is governed without a per-repo `init`. */\nfunction runInstall(args: string[]): void {\n const dir = userHome();\n const { agentKid, policyPath } = scaffold(dir, { force: args.includes(\"--force\") });\n console.log(`Scopebond installed for this user in ${dir}`);\n console.log(` machine key ${agentKid}`);\n console.log(` policy ${policyPath} (starter — edit the limits)`);\n console.log(\"\");\n const harnesses: Harness[] = args.includes(\"--codex\") ? [\"codex\"]\n : args.includes(\"--cursor\") ? [\"cursor\"]\n : args.includes(\"--claude\") ? [\"claude\"]\n : [\"claude\", ...(cursorDetected() ? [\"cursor\" as const] : []), ...(codexDetected() ? [\"codex\" as const] : [])];\n if (!args.includes(\"--no-install\")) {\n for (const h of harnesses) {\n const file = writeHarnessConfig(userHarnessFile(h), h, absoluteHookCommand(cliPath(), h));\n console.log(`✓ ${harnessName(h)} configured in ${file}`);\n }\n } else {\n console.log(\"Add this to your user-level agent config:\");\n console.log(harnessSnippet(harnesses[0]));\n }\n if (harnesses.includes(\"codex\")) console.log(`\\nOne last step for Codex: ${codexTrustStep}`);\n console.log(\"\");\n console.log(\"A project-local .scopebond still takes precedence when present.\");\n console.log(`Check it: ${cliCommand(\"doctor\")} · see decisions: ${cliCommand(\"log\")}`);\n console.log(`To send receipts to a workspace: ${cliCommand(\"connect <workspace-url> <enrollment>\")}`);\n}\n\nfunction runStatus(): void {\n const home = userHome();\n const installed = existsSync(join(home, \"policy.json\"));\n const claude = isHarnessConfigured(userHarnessFile(\"claude\"));\n const cursor = isHarnessConfigured(userHarnessFile(\"cursor\"));\n const codex = isHarnessConfigured(userHarnessFile(\"codex\"));\n const connected = !!loadConnection(resolveConfigDir(process.cwd()));\n const dbPath = join(resolveConfigDir(process.cwd()), \"receipts.db\");\n console.log(`Scopebond hook ${hookVersion()}`);\n console.log(` user home ${home} ${installed ? \"(installed)\" : \"(not installed — run `scopebond install`)\"}`);\n console.log(` active config ${resolveConfigDir(process.cwd())}`);\n console.log(` Claude Code ${claude ? \"configured\" : \"not configured\"}`);\n console.log(` Cursor ${cursor ? \"configured\" : cursorDetected() ? \"detected, not configured\" : \"not detected\"}`);\n console.log(` Codex ${codex ? \"configured (approve once with /hooks)\" : codexDetected() ? \"detected, not configured\" : \"not detected\"}`);\n console.log(` cloud workspace ${connected ? \"connected\" : \"not connected (local only)\"}`);\n console.log(` local receipts ${existsSync(dbPath) ? dbPath : \"none yet\"}`);\n}\n\nasync function runDoctor(): Promise<void> {\n const problems: string[] = [];\n const [major, minor] = process.versions.node.split(\".\").map(Number);\n const nodeOk = major > 22 || (major === 22 && minor >= 13);\n console.log(`Scopebond doctor`);\n console.log(` node ${process.versions.node} ${nodeOk ? \"ok\" : \"TOO OLD (need >=22.13)\"}`);\n if (!nodeOk) problems.push(\"node >=22.13 is required (the Cloud outbox uses node:sqlite)\");\n const cli = cliPath();\n console.log(` cli ${cli} ${existsSync(cli) ? \"ok\" : \"MISSING\"}`);\n const active = resolveConfigDir(process.cwd());\n const hasPolicy = existsSync(join(active, \"policy.json\"));\n console.log(` active config ${active} ${hasPolicy ? \"ok\" : \"no policy (run `scopebond install` or `init`)\"}`);\n if (!hasPolicy) problems.push(\"no policy found in the active config dir\");\n const codex = isHarnessConfigured(userHarnessFile(\"codex\"));\n console.log(` Codex hook ${codex ? \"configured\" : codexDetected() ? \"not configured — run `scopebond install --codex`\" : \"not detected\"}`);\n if (codex) console.log(` Codex approval run /hooks in Codex and approve Scopebond once`);\n const connection = loadConnection(active);\n if (!connection) {\n console.log(` cloud not connected (local only) — receipts stay on this machine`);\n } else {\n let reachable = \"unknown\";\n try {\n const res = await fetch(new URL(\"/healthz\", connection.url).toString(), { method: \"GET\" });\n reachable = res.ok ? \"reachable\" : `unhealthy (${res.status})`;\n } catch (error) { reachable = `unreachable (${(error as Error).message})`; }\n console.log(` cloud ${connection.url} — ${reachable}`);\n }\n console.log(problems.length ? `\\n${problems.length} problem(s): ${problems.join(\"; \")}` : `\\nAll good.`);\n process.exitCode = problems.length ? 1 : 0;\n}\n\nfunction runUninstall(args: string[]): void {\n let removed = 0;\n for (const h of [\"claude\", \"cursor\", \"codex\"] as Harness[]) {\n if (removeHarnessConfig(userHarnessFile(h))) { console.log(`✓ removed the Scopebond hook from ${userHarnessFile(h)}`); removed++; }\n }\n if (removed === 0) console.log(\"no user-level harness config found.\");\n if (args.includes(\"--purge\")) { purgeHome(); console.log(`✓ purged ${userHome()} (keys, policy, receipts)`); }\n else console.log(`Kept ${userHome()} (keys, policy, receipts). Use --purge to remove it too.`);\n}\n\nfunction runLogin(): void {\n console.log(\"Device-code login is not available yet.\");\n console.log(`For now, connect with a one-time enrollment from your workspace:`);\n console.log(` ${cliCommand(\"connect <workspace-url> <enrollment>\")}`);\n process.exit(0);\n}\n\nconst [cmd, ...rest] = process.argv.slice(2);\nif (cmd === \"claude\") { await runClaude(); }\nelse if (cmd === \"cursor\") { await runCursor(); }\nelse if (cmd === \"codex\") { await runCodex(); }\nelse if (cmd === \"init\") { runInit(rest); }\nelse if (cmd === \"install\") { runInstall(rest); }\nelse if (cmd === \"connect\") { await runConnect(rest); }\nelse if (cmd === \"log\") { await runLog(rest); }\nelse if (cmd === \"verify\") { await runVerify(); }\nelse if (cmd === \"test\") { await runTest(rest); }\nelse if (cmd === \"flush\") { await runFlush(); }\nelse if (cmd === \"status\") { runStatus(); }\nelse if (cmd === \"doctor\") { await runDoctor(); }\nelse if (cmd === \"uninstall\") { runUninstall(rest); }\nelse if (cmd === \"login\") { runLogin(); }\nelse {\n console.error(\"usage: scopebond <claude|cursor|codex|init|install|connect|log|verify|test|flush|status|doctor|uninstall|login> [--cursor] [--claude] [--codex] [--force] [--strict] [--no-install] [--purge]\");\n process.exit(1);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../src/cloud.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,qBAAqB,EAAE,KAAK,qBAAqB,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAC9F,MAAM,oBAAoB,CAAC;AAG5B;8EAC8E;AAC9E,MAAM,WAAW,cAAe,SAAQ,qBAAqB;IAC3D,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAAiC,CAAC;AAE/E,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAQjE;AAED;;wFAEwF;AACxF,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,GAChF,OAAO,CAAC,cAAc,CAAC,CAMzB;AAED;oFACoF;AACpF,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,GAC9F;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,CAIlD;AAED;kFACkF;AAClF,wBAAsB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3F"}
1
+ {"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../src/cloud.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,qBAAqB,EAAE,KAAK,qBAAqB,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAC9F,MAAM,oBAAoB,CAAC;AAG5B;8EAC8E;AAC9E,MAAM,WAAW,cAAe,SAAQ,qBAAqB;IAC3D,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MAAiC,CAAC;AAE/E,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAQjE;AAED;;wFAEwF;AACxF,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,GAChF,OAAO,CAAC,cAAc,CAAC,CAOzB;AAED;oFACoF;AACpF,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,GAC9F;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,CAIlD;AAED;kFACkF;AAClF,wBAAsB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3F"}
package/dist/cloud.js CHANGED
@@ -26,7 +26,8 @@ export function loadConnection(dir) {
26
26
  * here is the same key the hook countersigns receipts with, so ingest accepts them. */
27
27
  export async function connectCloud(dir, url, bundle, fetchImpl) {
28
28
  const { attester } = loadOrCreateAttester({ file: join(dir, "attester.key") });
29
- const result = await completeCloudEnrollment({ url, bundle, attester, fetch: fetchImpl });
29
+ const { attester: agent } = loadOrCreateAttester({ file: join(dir, "agent.key") });
30
+ const result = await completeCloudEnrollment({ url, bundle, attester, agent, fetch: fetchImpl });
30
31
  const connection = { url, ...result };
31
32
  writeFileSync(connectionPath(dir), JSON.stringify(connection, null, 2) + "\n", { mode: 0o600 });
32
33
  return connection;
package/dist/cloud.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cloud.js","sourceRoot":"","sources":["../src/cloud.ts"],"names":[],"mappings":"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","sourcesContent":["// scopebond-hook → Scopebond Cloud: enroll the machine's countersigning key with a\n// workspace and auto-export signed receipts to the hosted portal, so a connected\n// hook starts monitoring automatically. Reuses the gateway's enrollment and bounded\n// durable exporter (D40 — no new transport). The machine credential and the complete\n// receipt log stay local-first; export is best-effort and never blocks a tool call.\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n completeCloudEnrollment, createCloudExporter, withCloudExporter,\n type CloudEnrollmentBundle, type CloudEnrollmentResult, type CloudExporter, type ReceiptStore,\n} from \"@scopebond/gateway\";\nimport { SqliteCloudOutbox, loadOrCreateAttester } from \"@scopebond/gateway/node\";\n\n/** The persisted connection between this machine and a Cloud workspace. Holds the\n * scoped machine credential; treat cloud.json as a secret (written 0600). */\nexport interface HookConnection extends CloudEnrollmentResult {\n url: string;\n}\n\nexport const connectionPath = (dir: string): string => join(dir, \"cloud.json\");\n\n/** Read the persisted connection, or null when the hook is not connected to Cloud. */\nexport function loadConnection(dir: string): HookConnection | null {\n const path = connectionPath(dir);\n if (!existsSync(path)) return null;\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as Partial<HookConnection>;\n if (typeof parsed.url === \"string\" && typeof parsed.credential === \"string\") return parsed as HookConnection;\n } catch { /* fall through */ }\n return null;\n}\n\n/** Enroll the machine's attester with a workspace using the portal's one-use handoff,\n * then persist the scoped machine credential. The attester whose possession is proved\n * here is the same key the hook countersigns receipts with, so ingest accepts them. */\nexport async function connectCloud(\n dir: string, url: string, bundle: CloudEnrollmentBundle, fetchImpl?: typeof fetch,\n): Promise<HookConnection> {\n const { attester } = loadOrCreateAttester({ file: join(dir, \"attester.key\") });\n const result = await completeCloudEnrollment({ url, bundle, attester, fetch: fetchImpl });\n const connection: HookConnection = { url, ...result };\n writeFileSync(connectionPath(dir), JSON.stringify(connection, null, 2) + \"\\n\", { mode: 0o600 });\n return connection;\n}\n\n/** Wrap a receipt store so every stored receipt is enqueued to a durable outbox and\n * exported to Cloud. Returns the wrapped store and the exporter (flush + stop). */\nexport function attachExporter(\n outboxDbPath: string, connection: HookConnection, store: ReceiptStore, fetchImpl?: typeof fetch,\n): { store: ReceiptStore; exporter: CloudExporter } {\n const outbox = new SqliteCloudOutbox(outboxDbPath);\n const exporter = createCloudExporter({ url: connection.url, credential: connection.credential, outbox, fetch: fetchImpl });\n return { store: withCloudExporter(store, exporter), exporter };\n}\n\n/** Attempt delivery with a bounded timeout so a per-invocation hook never hangs the\n * agent; undelivered receipts stay in the durable outbox and flush next time. */\nexport async function flushBounded(exporter: CloudExporter, timeoutMs = 3000): Promise<void> {\n await Promise.race([\n exporter.flush().catch(() => {}),\n new Promise<void>((resolve) => setTimeout(resolve, Math.max(0, timeoutMs)).unref?.()),\n ]);\n}\n"]}
1
+ {"version":3,"file":"cloud.js","sourceRoot":"","sources":["../src/cloud.ts"],"names":[],"mappings":"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","sourcesContent":["// scopebond-hook → Scopebond Cloud: enroll the machine's countersigning key with a\n// workspace and auto-export signed receipts to the hosted portal, so a connected\n// hook starts monitoring automatically. Reuses the gateway's enrollment and bounded\n// durable exporter (D40 — no new transport). The machine credential and the complete\n// receipt log stay local-first; export is best-effort and never blocks a tool call.\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n completeCloudEnrollment, createCloudExporter, withCloudExporter,\n type CloudEnrollmentBundle, type CloudEnrollmentResult, type CloudExporter, type ReceiptStore,\n} from \"@scopebond/gateway\";\nimport { SqliteCloudOutbox, loadOrCreateAttester } from \"@scopebond/gateway/node\";\n\n/** The persisted connection between this machine and a Cloud workspace. Holds the\n * scoped machine credential; treat cloud.json as a secret (written 0600). */\nexport interface HookConnection extends CloudEnrollmentResult {\n url: string;\n}\n\nexport const connectionPath = (dir: string): string => join(dir, \"cloud.json\");\n\n/** Read the persisted connection, or null when the hook is not connected to Cloud. */\nexport function loadConnection(dir: string): HookConnection | null {\n const path = connectionPath(dir);\n if (!existsSync(path)) return null;\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as Partial<HookConnection>;\n if (typeof parsed.url === \"string\" && typeof parsed.credential === \"string\") return parsed as HookConnection;\n } catch { /* fall through */ }\n return null;\n}\n\n/** Enroll the machine's attester with a workspace using the portal's one-use handoff,\n * then persist the scoped machine credential. The attester whose possession is proved\n * here is the same key the hook countersigns receipts with, so ingest accepts them. */\nexport async function connectCloud(\n dir: string, url: string, bundle: CloudEnrollmentBundle, fetchImpl?: typeof fetch,\n): Promise<HookConnection> {\n const { attester } = loadOrCreateAttester({ file: join(dir, \"attester.key\") });\n const { attester: agent } = loadOrCreateAttester({ file: join(dir, \"agent.key\") });\n const result = await completeCloudEnrollment({ url, bundle, attester, agent, fetch: fetchImpl });\n const connection: HookConnection = { url, ...result };\n writeFileSync(connectionPath(dir), JSON.stringify(connection, null, 2) + \"\\n\", { mode: 0o600 });\n return connection;\n}\n\n/** Wrap a receipt store so every stored receipt is enqueued to a durable outbox and\n * exported to Cloud. Returns the wrapped store and the exporter (flush + stop). */\nexport function attachExporter(\n outboxDbPath: string, connection: HookConnection, store: ReceiptStore, fetchImpl?: typeof fetch,\n): { store: ReceiptStore; exporter: CloudExporter } {\n const outbox = new SqliteCloudOutbox(outboxDbPath);\n const exporter = createCloudExporter({ url: connection.url, credential: connection.credential, outbox, fetch: fetchImpl });\n return { store: withCloudExporter(store, exporter), exporter };\n}\n\n/** Attempt delivery with a bounded timeout so a per-invocation hook never hangs the\n * agent; undelivered receipts stay in the durable outbox and flush next time. */\nexport async function flushBounded(exporter: CloudExporter, timeoutMs = 3000): Promise<void> {\n await Promise.race([\n exporter.flush().catch(() => {}),\n new Promise<void>((resolve) => setTimeout(resolve, Math.max(0, timeoutMs)).unref?.()),\n ]);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
- export { mapClaudeToolUse, mapCursorEvent, fillPushBranch } from "./map.js";
1
+ export { mapClaudeToolUse, mapCodexToolUse, mapCursorEvent, fillPushBranch } from "./map.js";
2
2
  export type { Mapped, NormalizedIntent } from "./map.js";
3
3
  export { createHookRuntime, starterPolicy } from "./runtime.js";
4
4
  export type { RuntimeConfig, Decision } from "./runtime.js";
5
5
  export { scaffold, harnessSnippet, installHarness } from "./init.js";
6
+ export { userHome, userHarnessFile, resolveConfigDir, writeHarnessConfig, removeHarnessConfig, cursorDetected, codexDetected, absoluteHookCommand, isHarnessConfigured, purgeHome, } from "./install.js";
7
+ export type { Harness } from "./install.js";
6
8
  export { connectCloud, loadConnection, attachExporter, flushBounded, connectionPath } from "./cloud.js";
7
9
  export type { HookConnection } from "./cloud.js";
8
10
  export { scrubSecrets, scrubParam, redactCommand, digest, sha256 } from "./minimize.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC5E,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxG,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC7F,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EACL,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EACpF,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,SAAS,GACnF,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxG,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
- // @scopebond/hook — the Claude Code + Cursor connector. The library surface is
1
+ // @scopebond/hook — the Claude Code, Cursor + Codex connector. The library surface is
2
2
  // the deterministic mapper and the check-only runtime; the `scopebond-hook`
3
3
  // binary is the thin harness adapter over them.
4
- export { mapClaudeToolUse, mapCursorEvent, fillPushBranch } from "./map.js";
4
+ export { mapClaudeToolUse, mapCodexToolUse, mapCursorEvent, fillPushBranch } from "./map.js";
5
5
  export { createHookRuntime, starterPolicy } from "./runtime.js";
6
6
  export { scaffold, harnessSnippet, installHarness } from "./init.js";
7
+ export { userHome, userHarnessFile, resolveConfigDir, writeHarnessConfig, removeHarnessConfig, cursorDetected, codexDetected, absoluteHookCommand, isHarnessConfigured, purgeHome, } from "./install.js";
7
8
  export { connectCloud, loadConnection, attachExporter, flushBounded, connectionPath } from "./cloud.js";
8
9
  export { scrubSecrets, scrubParam, redactCommand, digest, sha256 } from "./minimize.js";
9
10
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,4EAA4E;AAC5E,gDAAgD;AAEhD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE5E,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAExG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC","sourcesContent":["// @scopebond/hook — the Claude Code + Cursor connector. The library surface is\n// the deterministic mapper and the check-only runtime; the `scopebond-hook`\n// binary is the thin harness adapter over them.\n\nexport { mapClaudeToolUse, mapCursorEvent, fillPushBranch } from \"./map.js\";\nexport type { Mapped, NormalizedIntent } from \"./map.js\";\nexport { createHookRuntime, starterPolicy } from \"./runtime.js\";\nexport type { RuntimeConfig, Decision } from \"./runtime.js\";\nexport { scaffold, harnessSnippet, installHarness } from \"./init.js\";\nexport { connectCloud, loadConnection, attachExporter, flushBounded, connectionPath } from \"./cloud.js\";\nexport type { HookConnection } from \"./cloud.js\";\nexport { scrubSecrets, scrubParam, redactCommand, digest, sha256 } from \"./minimize.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,4EAA4E;AAC5E,gDAAgD;AAEhD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE7F,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EACL,QAAQ,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EACpF,cAAc,EAAE,aAAa,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,SAAS,GACnF,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAExG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC","sourcesContent":["// @scopebond/hook — the Claude Code, Cursor + Codex connector. The library surface is\n// the deterministic mapper and the check-only runtime; the `scopebond-hook`\n// binary is the thin harness adapter over them.\n\nexport { mapClaudeToolUse, mapCodexToolUse, mapCursorEvent, fillPushBranch } from \"./map.js\";\nexport type { Mapped, NormalizedIntent } from \"./map.js\";\nexport { createHookRuntime, starterPolicy } from \"./runtime.js\";\nexport type { RuntimeConfig, Decision } from \"./runtime.js\";\nexport { scaffold, harnessSnippet, installHarness } from \"./init.js\";\nexport {\n userHome, userHarnessFile, resolveConfigDir, writeHarnessConfig, removeHarnessConfig,\n cursorDetected, codexDetected, absoluteHookCommand, isHarnessConfigured, purgeHome,\n} from \"./install.js\";\nexport type { Harness } from \"./install.js\";\nexport { connectCloud, loadConnection, attachExporter, flushBounded, connectionPath } from \"./cloud.js\";\nexport type { HookConnection } from \"./cloud.js\";\nexport { scrubSecrets, scrubParam, redactCommand, digest, sha256 } from \"./minimize.js\";\n"]}
package/dist/init.d.ts CHANGED
@@ -8,7 +8,7 @@ export declare function scaffold(dir: string, opts?: {
8
8
  * there (idempotent — safe to run twice). Returns the file it wrote. This is what
9
9
  * lets `connect` finish setup without the user hand-editing JSON.
10
10
  * `cwd` defaults to the current directory (the project root the user runs it in). */
11
- export declare function installHarness(harness: "claude" | "cursor", cwd?: string): string;
11
+ export declare function installHarness(harness: "claude" | "cursor" | "codex", cwd?: string): string;
12
12
  /** The harness configuration snippet to install the hook (version-pinned npx). */
13
- export declare function harnessSnippet(harness: "claude" | "cursor"): string;
13
+ export declare function harnessSnippet(harness: "claude" | "cursor" | "codex"): string;
14
14
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAWA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAgB9G;AAED;;;sFAGsF;AACtF,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CA6BhG;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAkBnE"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAWA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAgB9G;AAED;;;sFAGsF;AACtF,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAmC1G;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CA2B7E"}
package/dist/init.js CHANGED
@@ -31,7 +31,9 @@ export function scaffold(dir, opts = {}) {
31
31
  * `cwd` defaults to the current directory (the project root the user runs it in). */
32
32
  export function installHarness(harness, cwd = process.cwd()) {
33
33
  const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
34
- const file = harness === "cursor" ? join(cwd, ".cursor", "hooks.json") : join(cwd, ".claude", "settings.json");
34
+ const file = harness === "cursor" ? join(cwd, ".cursor", "hooks.json")
35
+ : harness === "codex" ? join(cwd, ".codex", "hooks.json")
36
+ : join(cwd, ".claude", "settings.json");
35
37
  mkdirSync(dirname(file), { recursive: true });
36
38
  let config = {};
37
39
  if (existsSync(file)) {
@@ -45,6 +47,7 @@ export function installHarness(harness, cwd = process.cwd()) {
45
47
  const hooks = isRecord(config.hooks) ? config.hooks : (config.hooks = {});
46
48
  const cursorCmd = hookCommand("cursor");
47
49
  const claudeCmd = hookCommand("claude");
50
+ const codexCmd = hookCommand("codex");
48
51
  // Match any existing Scopebond hook entry (pinned or a legacy bare `scopebond-hook`)
49
52
  // so re-running never appends a duplicate and an old bare command is replaced.
50
53
  const isScopebond = (cmd) => typeof cmd === "string" && /(^|\s)(npx\s+.*)?@scopebond\/hook|(^|\s)scopebond-hook(\s|$)/.test(cmd);
@@ -63,7 +66,10 @@ export function installHarness(harness, cwd = process.cwd()) {
63
66
  else {
64
67
  const list = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : (hooks.PreToolUse = []);
65
68
  const existing = list.findIndex(entryMatches);
66
- const entry = { matcher: "*", hooks: [{ type: "command", command: claudeCmd }] };
69
+ // Codex matchers are regular expressions. No matcher means all supported tools.
70
+ const entry = harness === "codex"
71
+ ? { hooks: [{ type: "command", command: codexCmd, timeout: 30, statusMessage: "Checking this action with Scopebond" }] }
72
+ : { matcher: "*", hooks: [{ type: "command", command: claudeCmd }] };
67
73
  if (existing >= 0)
68
74
  list[existing] = entry;
69
75
  else
@@ -86,6 +92,15 @@ export function harnessSnippet(harness) {
86
92
  },
87
93
  }, null, 2);
88
94
  }
95
+ if (harness === "codex") {
96
+ return JSON.stringify({
97
+ hooks: {
98
+ PreToolUse: [{
99
+ hooks: [{ type: "command", command: hookCommand("codex"), timeout: 30, statusMessage: "Checking this action with Scopebond" }],
100
+ }],
101
+ },
102
+ }, null, 2);
103
+ }
89
104
  return JSON.stringify({
90
105
  hooks: {
91
106
  PreToolUse: [{ matcher: "*", hooks: [{ type: "command", command: hookCommand("claude") }] }],
package/dist/init.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["// `scopebond-hook init` — scaffold the local enrollment: a machine signing key, a\n// gateway countersigning key and a starter policy. Keys and receipts stay on the\n// machine; no credentials are handled.\n\nimport { mkdirSync, writeFileSync, existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { loadOrCreateAttester } from \"@scopebond/gateway/node\";\nimport { createSigner } from \"@scopebond/sdk\";\nimport { starterPolicy } from \"./runtime.js\";\nimport { hookCommand } from \"./version.js\";\n\nexport function scaffold(dir: string, opts: { force?: boolean } = {}): { agentKid: string; policyPath: string } {\n mkdirSync(dir, { recursive: true });\n const keyPath = join(dir, \"agent.key\");\n const attesterPath = join(dir, \"attester.key\");\n const policyPath = join(dir, \"policy.json\");\n // Never let the signing keys, the Cloud credential or the local log be committed.\n const gitignorePath = join(dir, \".gitignore\");\n if (!existsSync(gitignorePath)) writeFileSync(gitignorePath, \"*\\n\");\n // Machine signing key (agent) + gateway countersigning key (attester). Reused if present.\n loadOrCreateAttester({ file: keyPath });\n loadOrCreateAttester({ file: attesterPath });\n const agent = createSigner({ privateKeyPem: readFileSync(keyPath, \"utf8\") });\n if (!existsSync(policyPath) || opts.force) {\n writeFileSync(policyPath, JSON.stringify(starterPolicy(agent.kid), null, 2) + \"\\n\");\n }\n return { agentKid: agent.kid, policyPath };\n}\n\n/** Install the hook into the agent's own config file, merging with anything already\n * there (idempotent — safe to run twice). Returns the file it wrote. This is what\n * lets `connect` finish setup without the user hand-editing JSON.\n * `cwd` defaults to the current directory (the project root the user runs it in). */\nexport function installHarness(harness: \"claude\" | \"cursor\", cwd: string = process.cwd()): string {\n const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === \"object\" && v !== null && !Array.isArray(v);\n const file = harness === \"cursor\" ? join(cwd, \".cursor\", \"hooks.json\") : join(cwd, \".claude\", \"settings.json\");\n mkdirSync(dirname(file), { recursive: true });\n let config: Record<string, unknown> = {};\n if (existsSync(file)) { try { const p = JSON.parse(readFileSync(file, \"utf8\")); if (isRecord(p)) config = p; } catch { /* start fresh on unreadable */ } }\n const hooks = isRecord(config.hooks) ? config.hooks : (config.hooks = {});\n const cursorCmd = hookCommand(\"cursor\");\n const claudeCmd = hookCommand(\"claude\");\n // Match any existing Scopebond hook entry (pinned or a legacy bare `scopebond-hook`)\n // so re-running never appends a duplicate and an old bare command is replaced.\n const isScopebond = (cmd: unknown): boolean => typeof cmd === \"string\" && /(^|\\s)(npx\\s+.*)?@scopebond\\/hook|(^|\\s)scopebond-hook(\\s|$)/.test(cmd);\n const entryMatches = (e: unknown): boolean =>\n isRecord(e) && (isScopebond(e.command) || (Array.isArray(e.hooks) && e.hooks.some((h) => isRecord(h) && isScopebond(h.command))));\n if (harness === \"cursor\") {\n config.version = config.version ?? 1;\n for (const event of [\"beforeShellExecution\", \"beforeMCPExecution\", \"beforeReadFile\", \"afterFileEdit\"]) {\n const list = Array.isArray((hooks as Record<string, unknown>)[event]) ? (hooks as Record<string, unknown[]>)[event] : ((hooks as Record<string, unknown[]>)[event] = []);\n const existing = list.findIndex(entryMatches);\n if (existing >= 0) list[existing] = { command: cursorCmd }; else list.push({ command: cursorCmd });\n }\n } else {\n const list = Array.isArray((hooks as Record<string, unknown>).PreToolUse) ? (hooks as Record<string, unknown[]>).PreToolUse : ((hooks as Record<string, unknown[]>).PreToolUse = []);\n const existing = list.findIndex(entryMatches);\n const entry = { matcher: \"*\", hooks: [{ type: \"command\", command: claudeCmd }] };\n if (existing >= 0) list[existing] = entry; else list.push(entry);\n }\n writeFileSync(file, JSON.stringify(config, null, 2) + \"\\n\");\n return file;\n}\n\n/** The harness configuration snippet to install the hook (version-pinned npx). */\nexport function harnessSnippet(harness: \"claude\" | \"cursor\"): string {\n if (harness === \"cursor\") {\n const cmd = hookCommand(\"cursor\");\n return JSON.stringify({\n version: 1,\n hooks: {\n beforeShellExecution: [{ command: cmd }],\n beforeMCPExecution: [{ command: cmd }],\n beforeReadFile: [{ command: cmd }],\n afterFileEdit: [{ command: cmd }],\n },\n }, null, 2);\n }\n return JSON.stringify({\n hooks: {\n PreToolUse: [{ matcher: \"*\", hooks: [{ type: \"command\", command: hookCommand(\"claude\") }] }],\n },\n }, null, 2);\n}\n"]}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["// `scopebond-hook init` — scaffold the local enrollment: a machine signing key, a\n// gateway countersigning key and a starter policy. Keys and receipts stay on the\n// machine; no credentials are handled.\n\nimport { mkdirSync, writeFileSync, existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { loadOrCreateAttester } from \"@scopebond/gateway/node\";\nimport { createSigner } from \"@scopebond/sdk\";\nimport { starterPolicy } from \"./runtime.js\";\nimport { hookCommand } from \"./version.js\";\n\nexport function scaffold(dir: string, opts: { force?: boolean } = {}): { agentKid: string; policyPath: string } {\n mkdirSync(dir, { recursive: true });\n const keyPath = join(dir, \"agent.key\");\n const attesterPath = join(dir, \"attester.key\");\n const policyPath = join(dir, \"policy.json\");\n // Never let the signing keys, the Cloud credential or the local log be committed.\n const gitignorePath = join(dir, \".gitignore\");\n if (!existsSync(gitignorePath)) writeFileSync(gitignorePath, \"*\\n\");\n // Machine signing key (agent) + gateway countersigning key (attester). Reused if present.\n loadOrCreateAttester({ file: keyPath });\n loadOrCreateAttester({ file: attesterPath });\n const agent = createSigner({ privateKeyPem: readFileSync(keyPath, \"utf8\") });\n if (!existsSync(policyPath) || opts.force) {\n writeFileSync(policyPath, JSON.stringify(starterPolicy(agent.kid), null, 2) + \"\\n\");\n }\n return { agentKid: agent.kid, policyPath };\n}\n\n/** Install the hook into the agent's own config file, merging with anything already\n * there (idempotent — safe to run twice). Returns the file it wrote. This is what\n * lets `connect` finish setup without the user hand-editing JSON.\n * `cwd` defaults to the current directory (the project root the user runs it in). */\nexport function installHarness(harness: \"claude\" | \"cursor\" | \"codex\", cwd: string = process.cwd()): string {\n const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === \"object\" && v !== null && !Array.isArray(v);\n const file = harness === \"cursor\" ? join(cwd, \".cursor\", \"hooks.json\")\n : harness === \"codex\" ? join(cwd, \".codex\", \"hooks.json\")\n : join(cwd, \".claude\", \"settings.json\");\n mkdirSync(dirname(file), { recursive: true });\n let config: Record<string, unknown> = {};\n if (existsSync(file)) { try { const p = JSON.parse(readFileSync(file, \"utf8\")); if (isRecord(p)) config = p; } catch { /* start fresh on unreadable */ } }\n const hooks = isRecord(config.hooks) ? config.hooks : (config.hooks = {});\n const cursorCmd = hookCommand(\"cursor\");\n const claudeCmd = hookCommand(\"claude\");\n const codexCmd = hookCommand(\"codex\");\n // Match any existing Scopebond hook entry (pinned or a legacy bare `scopebond-hook`)\n // so re-running never appends a duplicate and an old bare command is replaced.\n const isScopebond = (cmd: unknown): boolean => typeof cmd === \"string\" && /(^|\\s)(npx\\s+.*)?@scopebond\\/hook|(^|\\s)scopebond-hook(\\s|$)/.test(cmd);\n const entryMatches = (e: unknown): boolean =>\n isRecord(e) && (isScopebond(e.command) || (Array.isArray(e.hooks) && e.hooks.some((h) => isRecord(h) && isScopebond(h.command))));\n if (harness === \"cursor\") {\n config.version = config.version ?? 1;\n for (const event of [\"beforeShellExecution\", \"beforeMCPExecution\", \"beforeReadFile\", \"afterFileEdit\"]) {\n const list = Array.isArray((hooks as Record<string, unknown>)[event]) ? (hooks as Record<string, unknown[]>)[event] : ((hooks as Record<string, unknown[]>)[event] = []);\n const existing = list.findIndex(entryMatches);\n if (existing >= 0) list[existing] = { command: cursorCmd }; else list.push({ command: cursorCmd });\n }\n } else {\n const list = Array.isArray((hooks as Record<string, unknown>).PreToolUse) ? (hooks as Record<string, unknown[]>).PreToolUse : ((hooks as Record<string, unknown[]>).PreToolUse = []);\n const existing = list.findIndex(entryMatches);\n // Codex matchers are regular expressions. No matcher means all supported tools.\n const entry = harness === \"codex\"\n ? { hooks: [{ type: \"command\", command: codexCmd, timeout: 30, statusMessage: \"Checking this action with Scopebond\" }] }\n : { matcher: \"*\", hooks: [{ type: \"command\", command: claudeCmd }] };\n if (existing >= 0) list[existing] = entry; else list.push(entry);\n }\n writeFileSync(file, JSON.stringify(config, null, 2) + \"\\n\");\n return file;\n}\n\n/** The harness configuration snippet to install the hook (version-pinned npx). */\nexport function harnessSnippet(harness: \"claude\" | \"cursor\" | \"codex\"): string {\n if (harness === \"cursor\") {\n const cmd = hookCommand(\"cursor\");\n return JSON.stringify({\n version: 1,\n hooks: {\n beforeShellExecution: [{ command: cmd }],\n beforeMCPExecution: [{ command: cmd }],\n beforeReadFile: [{ command: cmd }],\n afterFileEdit: [{ command: cmd }],\n },\n }, null, 2);\n }\n if (harness === \"codex\") {\n return JSON.stringify({\n hooks: {\n PreToolUse: [{\n hooks: [{ type: \"command\", command: hookCommand(\"codex\"), timeout: 30, statusMessage: \"Checking this action with Scopebond\" }],\n }],\n },\n }, null, 2);\n }\n return JSON.stringify({\n hooks: {\n PreToolUse: [{ matcher: \"*\", hooks: [{ type: \"command\", command: hookCommand(\"claude\") }] }],\n },\n }, null, 2);\n}\n"]}
@@ -0,0 +1,28 @@
1
+ export type Harness = "claude" | "cursor" | "codex";
2
+ /** The user-level Scopebond home. `SCOPEBOND_HOME` overrides it (tests, CI). */
3
+ export declare function userHome(): string;
4
+ /** The user-level agent config file for a harness. `HOME`/`USERPROFILE` (via homedir)
5
+ * roots it; SCOPEBOND_HOME does not move the agent's own config. */
6
+ export declare function userHarnessFile(harness: Harness): string;
7
+ /** Resolve the config dir for a hook event, most specific first:
8
+ * explicit override → the payload's project → $CLAUDE_PROJECT_DIR → the user home.
9
+ * A project dir counts only when it has been scaffolded (a policy.json), so a bare
10
+ * working directory never shadows the user-level install. */
11
+ export declare function resolveConfigDir(payloadCwd: string | undefined): string;
12
+ /** Write (idempotently) a harness hook entry pointing at an explicit command string.
13
+ * Shared by the project installer (npx command) and the user installer (absolute path). */
14
+ export declare function writeHarnessConfig(file: string, harness: Harness, command: string): string;
15
+ /** Remove any Scopebond hook entry from a user-level harness config, leaving the rest
16
+ * intact. Returns true if the file existed. */
17
+ export declare function removeHarnessConfig(file: string): boolean;
18
+ /** Detect a Cursor install by its user config directory. */
19
+ export declare function cursorDetected(): boolean;
20
+ /** Detect a Codex install by its user config directory. */
21
+ export declare function codexDetected(): boolean;
22
+ /** The absolute command a user-level harness entry runs: the current Node executable
23
+ * and the absolute path to this CLI, so it does not depend on PATH. */
24
+ export declare function absoluteHookCommand(cliPath: string, harness: Harness): string;
25
+ export declare function isHarnessConfigured(file: string): boolean;
26
+ /** Remove the user-level home (keys, policy, receipts). */
27
+ export declare function purgeHome(): void;
28
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpD,gFAAgF;AAChF,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED;qEACqE;AACrE,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAIxD;AAED;;;8DAG8D;AAC9D,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAYvE;AAaD;4FAC4F;AAC5F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAyB1F;AAED;gDACgD;AAChD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUzD;AAED,4DAA4D;AAC5D,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,2DAA2D;AAC3D,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;wEACwE;AACxE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAG7E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED,2DAA2D;AAC3D,wBAAgB,SAAS,IAAI,IAAI,CAEhC"}
@@ -0,0 +1,144 @@
1
+ // SB112 — the user-level installer. One install per developer machine (not per repo):
2
+ // keys and a starter policy live in a user-level home (~/.scopebond, override
3
+ // SCOPEBOND_HOME), and the hook is registered by absolute path in the user-level agent
4
+ // config (~/.claude/settings.json, ~/.cursor/hooks.json, ~/.codex/hooks.json). A project-local `.scopebond`
5
+ // still wins when present, so per-project policies keep working.
6
+ import { mkdirSync, writeFileSync, existsSync, readFileSync, rmSync } from "node:fs";
7
+ import { homedir } from "node:os";
8
+ import { dirname, join } from "node:path";
9
+ /** The user-level Scopebond home. `SCOPEBOND_HOME` overrides it (tests, CI). */
10
+ export function userHome() {
11
+ return process.env.SCOPEBOND_HOME ?? join(homedir(), ".scopebond");
12
+ }
13
+ /** The user-level agent config file for a harness. `HOME`/`USERPROFILE` (via homedir)
14
+ * roots it; SCOPEBOND_HOME does not move the agent's own config. */
15
+ export function userHarnessFile(harness) {
16
+ if (harness === "cursor")
17
+ return join(homedir(), ".cursor", "hooks.json");
18
+ if (harness === "codex")
19
+ return join(homedir(), ".codex", "hooks.json");
20
+ return join(homedir(), ".claude", "settings.json");
21
+ }
22
+ /** Resolve the config dir for a hook event, most specific first:
23
+ * explicit override → the payload's project → $CLAUDE_PROJECT_DIR → the user home.
24
+ * A project dir counts only when it has been scaffolded (a policy.json), so a bare
25
+ * working directory never shadows the user-level install. */
26
+ export function resolveConfigDir(payloadCwd) {
27
+ if (process.env.SCOPEBOND_HOOK_DIR)
28
+ return process.env.SCOPEBOND_HOOK_DIR;
29
+ const candidates = [];
30
+ if (payloadCwd)
31
+ candidates.push(join(payloadCwd, ".scopebond"));
32
+ if (process.env.CLAUDE_PROJECT_DIR)
33
+ candidates.push(join(process.env.CLAUDE_PROJECT_DIR, ".scopebond"));
34
+ for (const dir of candidates) {
35
+ if (existsSync(join(dir, "policy.json")))
36
+ return dir;
37
+ }
38
+ const home = userHome();
39
+ if (existsSync(join(home, "policy.json")))
40
+ return home;
41
+ // Nothing scaffolded yet: prefer the payload project, else the user home.
42
+ return candidates[0] ?? home;
43
+ }
44
+ const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
45
+ const isScopebond = (cmd) => typeof cmd === "string" && (/@scopebond\/hook|scopebond-hook(\s|$)/.test(cmd) ||
46
+ // the user-level absolute form: `<node> <…/cli.js> claude|cursor|codex`
47
+ /cli\.js["']?\s+(claude|cursor|codex)\s*$/.test(cmd) ||
48
+ /(^|["\s])scopebond(["'\s]).*\b(claude|cursor|codex)\b/.test(cmd));
49
+ const entryMatches = (e) => isRecord(e) && (isScopebond(e.command) || (Array.isArray(e.hooks) && e.hooks.some((h) => isRecord(h) && isScopebond(h.command))));
50
+ /** Write (idempotently) a harness hook entry pointing at an explicit command string.
51
+ * Shared by the project installer (npx command) and the user installer (absolute path). */
52
+ export function writeHarnessConfig(file, harness, command) {
53
+ mkdirSync(dirname(file), { recursive: true });
54
+ let config = {};
55
+ if (existsSync(file)) {
56
+ try {
57
+ const p = JSON.parse(readFileSync(file, "utf8"));
58
+ if (isRecord(p))
59
+ config = p;
60
+ }
61
+ catch { /* start fresh on unreadable */ }
62
+ }
63
+ const hooks = isRecord(config.hooks) ? config.hooks : (config.hooks = {});
64
+ if (harness === "cursor") {
65
+ config.version = config.version ?? 1;
66
+ for (const event of ["beforeShellExecution", "beforeMCPExecution", "beforeReadFile", "afterFileEdit"]) {
67
+ const list = Array.isArray(hooks[event]) ? hooks[event] : (hooks[event] = []);
68
+ const at = list.findIndex(entryMatches);
69
+ const entry = { command: command.replace(/\bclaude$/, "cursor") };
70
+ if (at >= 0)
71
+ list[at] = entry;
72
+ else
73
+ list.push(entry);
74
+ }
75
+ }
76
+ else {
77
+ const list = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : (hooks.PreToolUse = []);
78
+ const at = list.findIndex(entryMatches);
79
+ // Codex matchers are regular expressions; omitting the matcher means every tool.
80
+ // A literal "*" is not a valid regular expression and causes Codex to skip the group.
81
+ const entry = harness === "codex"
82
+ ? { hooks: [{ type: "command", command, timeout: 30, statusMessage: "Checking this action with Scopebond" }] }
83
+ : { matcher: "*", hooks: [{ type: "command", command }] };
84
+ if (at >= 0)
85
+ list[at] = entry;
86
+ else
87
+ list.push(entry);
88
+ }
89
+ writeFileSync(file, JSON.stringify(config, null, 2) + "\n");
90
+ return file;
91
+ }
92
+ /** Remove any Scopebond hook entry from a user-level harness config, leaving the rest
93
+ * intact. Returns true if the file existed. */
94
+ export function removeHarnessConfig(file) {
95
+ if (!existsSync(file))
96
+ return false;
97
+ let config;
98
+ try {
99
+ const p = JSON.parse(readFileSync(file, "utf8"));
100
+ config = isRecord(p) ? p : {};
101
+ }
102
+ catch {
103
+ return true;
104
+ }
105
+ const hooks = isRecord(config.hooks) ? config.hooks : {};
106
+ for (const [event, value] of Object.entries(hooks)) {
107
+ if (Array.isArray(value))
108
+ hooks[event] = value.filter((e) => !entryMatches(e));
109
+ }
110
+ writeFileSync(file, JSON.stringify(config, null, 2) + "\n");
111
+ return true;
112
+ }
113
+ /** Detect a Cursor install by its user config directory. */
114
+ export function cursorDetected() {
115
+ return existsSync(join(homedir(), ".cursor"));
116
+ }
117
+ /** Detect a Codex install by its user config directory. */
118
+ export function codexDetected() {
119
+ return existsSync(join(homedir(), ".codex"));
120
+ }
121
+ /** The absolute command a user-level harness entry runs: the current Node executable
122
+ * and the absolute path to this CLI, so it does not depend on PATH. */
123
+ export function absoluteHookCommand(cliPath, harness) {
124
+ const quote = (s) => (/\s/.test(s) ? `"${s}"` : s);
125
+ return `${quote(process.execPath)} ${quote(cliPath)} ${harness}`;
126
+ }
127
+ export function isHarnessConfigured(file) {
128
+ if (!existsSync(file))
129
+ return false;
130
+ try {
131
+ const p = JSON.parse(readFileSync(file, "utf8"));
132
+ if (!isRecord(p) || !isRecord(p.hooks))
133
+ return false;
134
+ return Object.values(p.hooks).some((v) => Array.isArray(v) && v.some(entryMatches));
135
+ }
136
+ catch {
137
+ return false;
138
+ }
139
+ }
140
+ /** Remove the user-level home (keys, policy, receipts). */
141
+ export function purgeHome() {
142
+ rmSync(userHome(), { recursive: true, force: true });
143
+ }
144
+ //# sourceMappingURL=install.js.map