approval-box 0.1.4 → 0.1.6
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/README.md +2 -2
- package/dist/approval-box-claude-hook.mjs +1 -1
- package/dist/approval-box-codex-hook.mjs +1 -1
- package/dist/approval-box-cursor-hook.mjs +1 -1
- package/dist/approval-box-receive.mjs +1 -1
- package/dist/chunks/{chunk-EZ7CZDGK.mjs → chunk-LEWADASG.mjs} +1 -0
- package/dist/cli.mjs +35 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,8 +14,8 @@ npx -y approval-box@latest setup
|
|
|
14
14
|
|
|
15
15
|
1. `setup` finds the agents on this machine and registers Approval Box (MCP server and hooks). It shows the files it will change and keeps a backup (`*.approval-box-backup`) before writing.
|
|
16
16
|
PCにあるAIを見つけて登録します。書き換えるファイルを先に見せ、控えを残してから書き換えます。
|
|
17
|
-
It also offers to add one short paragraph to each agent's global instructions (`~/.claude/CLAUDE.md`, `$CODEX_HOME/AGENTS.md`, `~/.grok/AGENTS.md`) so the agent also files decisions, approvals and actions with `request_decision`. Cursor
|
|
18
|
-
AIが毎回読む全体の指示に「判断・承認・操作が要る時は request_decision でも申請する」という一節を足すかを聞きます。Cursor
|
|
17
|
+
It also offers to add one short paragraph to each agent's global instructions (`~/.claude/CLAUDE.md`, `$CODEX_HOME/AGENTS.md`, `~/.grok/AGENTS.md`) so the agent also files decisions, approvals and actions with `request_decision`. Cursor does not read a global file, so setup passes the same text through a `sessionStart` hook in `~/.cursor/hooks.json`. Skip with `--no-instructions`.
|
|
18
|
+
AIが毎回読む全体の指示に「判断・承認・操作が要る時は request_decision でも申請する」という一節を足すかを聞きます。Cursor はファイルから読まないので、会話の始まりのhook(`~/.cursor/hooks.json` の sessionStart)で渡します。足さない時は `--no-instructions`。
|
|
19
19
|
2. Scan the QR code or enter the code in “Add device” in the app or web.
|
|
20
20
|
画面のQRコードかコードを、アプリかWeb版の「端末を追加」で読み取ります。
|
|
21
21
|
3. Tell your agent: `Approval Boxのsetup_testを実行して` (or “run Approval Box setup_test”). Answer the test request; when the answer reaches the agent, you are ready.
|
|
@@ -2,7 +2,7 @@ import { createRequire as __kbCreateRequire } from 'node:module'; const require
|
|
|
2
2
|
import {
|
|
3
3
|
PROFILE,
|
|
4
4
|
runCodexHookMain
|
|
5
|
-
} from "./chunks/chunk-
|
|
5
|
+
} from "./chunks/chunk-LEWADASG.mjs";
|
|
6
6
|
|
|
7
7
|
// src/hooks/codex.ts
|
|
8
8
|
await runCodexHookMain(PROFILE, process.argv[2]);
|
|
@@ -2,7 +2,7 @@ import { createRequire as __kbCreateRequire } from 'node:module'; const require
|
|
|
2
2
|
import {
|
|
3
3
|
PROFILE,
|
|
4
4
|
runChannelReceiveMain
|
|
5
|
-
} from "./chunks/chunk-
|
|
5
|
+
} from "./chunks/chunk-LEWADASG.mjs";
|
|
6
6
|
|
|
7
7
|
// src/hooks/receive.ts
|
|
8
8
|
await runChannelReceiveMain(PROFILE);
|
|
@@ -21949,6 +21949,7 @@ export {
|
|
|
21949
21949
|
waitProcessCommandLine,
|
|
21950
21950
|
mergeClaudeParentHooks,
|
|
21951
21951
|
removeClaudeParentHooks,
|
|
21952
|
+
cursorParentHookCommand,
|
|
21952
21953
|
mergeCursorParentHooks,
|
|
21953
21954
|
removeCursorParentHooks,
|
|
21954
21955
|
openChannel,
|
package/dist/cli.mjs
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
codexParentFromRequest,
|
|
21
21
|
configureCodexSteer,
|
|
22
22
|
cursorHookRoot,
|
|
23
|
+
cursorParentHookCommand,
|
|
23
24
|
cursorParentHooksRegistered,
|
|
24
25
|
custom,
|
|
25
26
|
discriminatedUnion,
|
|
@@ -51,7 +52,7 @@ import {
|
|
|
51
52
|
verifyCursorParent,
|
|
52
53
|
waitProcessCommandLine,
|
|
53
54
|
withCodexReceiver
|
|
54
|
-
} from "./chunks/chunk-
|
|
55
|
+
} from "./chunks/chunk-LEWADASG.mjs";
|
|
55
56
|
|
|
56
57
|
// ../../node_modules/qrcode/lib/can-promise.js
|
|
57
58
|
var require_can_promise = __commonJS({
|
|
@@ -12048,7 +12049,7 @@ async function runDaemon() {
|
|
|
12048
12049
|
|
|
12049
12050
|
// src/harness.ts
|
|
12050
12051
|
import { execFileSync } from "node:child_process";
|
|
12051
|
-
import { copyFileSync, existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
12052
|
+
import { copyFileSync, existsSync as existsSync4, readFileSync as readFileSync4, realpathSync } from "node:fs";
|
|
12052
12053
|
import { homedir } from "node:os";
|
|
12053
12054
|
import { delimiter, dirname as dirname4, join as join4 } from "node:path";
|
|
12054
12055
|
|
|
@@ -12136,6 +12137,22 @@ function setCursorPermissions(enable) {
|
|
|
12136
12137
|
if (enable) allow.push(...ours);
|
|
12137
12138
|
writeJsonFile(file, { ...current, permissions: { ...permissions, allow, deny: permissions.deny ?? [] } });
|
|
12138
12139
|
}
|
|
12140
|
+
var CURSOR_CONTEXT = "cursor-context";
|
|
12141
|
+
function setCursorContext(enable) {
|
|
12142
|
+
const file = join4(cursorDir(), "hooks.json");
|
|
12143
|
+
if (!existsSync4(file) && !enable) return;
|
|
12144
|
+
const target = existsSync4(file) ? realpathSync(file) : file;
|
|
12145
|
+
backupOnce(target);
|
|
12146
|
+
const current = existsSync4(target) ? readJson(target) : { version: 1 };
|
|
12147
|
+
const hooks = { ...current.hooks ?? {} };
|
|
12148
|
+
const ours = (entry) => typeof entry?.command === "string" && entry.command.includes(MCP_SERVER) && entry.command.endsWith(` ${CURSOR_CONTEXT}`);
|
|
12149
|
+
const rest = (hooks.sessionStart ?? []).filter((entry) => !ours(entry));
|
|
12150
|
+
if (enable) rest.push({ command: `${cursorParentHookCommand({ command: stableNode(), script: runtimeEntry("cli") })} ${CURSOR_CONTEXT}`, timeout: 10 });
|
|
12151
|
+
if (rest.length) hooks.sessionStart = rest;
|
|
12152
|
+
else delete hooks.sessionStart;
|
|
12153
|
+
writeJsonFile(target, { version: 1, ...current, hooks });
|
|
12154
|
+
}
|
|
12155
|
+
var cursorContextRegistered = () => JSON.stringify(readJson(join4(cursorDir(), "hooks.json")).hooks ?? {}).includes(` ${CURSOR_CONTEXT}"`);
|
|
12139
12156
|
var registration = () => ({ command: stableNode(), args: [runtimeEntry("cli"), "mcp"] });
|
|
12140
12157
|
function readJson(file) {
|
|
12141
12158
|
if (!existsSync4(file)) return {};
|
|
@@ -12176,6 +12193,7 @@ async function register(target, options = {}) {
|
|
|
12176
12193
|
setMcpJson(join4(cursorDir(), "mcp.json"), registration());
|
|
12177
12194
|
mergeCursorParentHooks(PROFILE, join4(cursorDir(), "hooks.json"), hook("cursor"));
|
|
12178
12195
|
setCursorPermissions(true);
|
|
12196
|
+
setCursorContext(!!options.instructions);
|
|
12179
12197
|
return { target, status: "registered" };
|
|
12180
12198
|
}
|
|
12181
12199
|
if (target === "codex") {
|
|
@@ -12214,6 +12232,7 @@ async function unregister(target) {
|
|
|
12214
12232
|
if (existsSync4(join4(cursorDir(), "mcp.json"))) setMcpJson(join4(cursorDir(), "mcp.json"), null);
|
|
12215
12233
|
removeCursorParentHooks(PROFILE, join4(cursorDir(), "hooks.json"));
|
|
12216
12234
|
setCursorPermissions(false);
|
|
12235
|
+
setCursorContext(false);
|
|
12217
12236
|
} else if (target === "codex") {
|
|
12218
12237
|
if (existsSync4(join4(codexHome(), "config.toml"))) {
|
|
12219
12238
|
await withCodexConfig(async (request) => {
|
|
@@ -12235,7 +12254,7 @@ async function unregister(target) {
|
|
|
12235
12254
|
}
|
|
12236
12255
|
function registered(target) {
|
|
12237
12256
|
const file = instructionsFileOf(target);
|
|
12238
|
-
return { ...registeredTools(target), instructions: file ? hasInstructions(file) : null };
|
|
12257
|
+
return { ...registeredTools(target), instructions: file ? hasInstructions(file) : target === "cursor" ? cursorContextRegistered() : null };
|
|
12239
12258
|
}
|
|
12240
12259
|
function registeredTools(target) {
|
|
12241
12260
|
const entryOf = (value) => (value?.args ?? [])[0];
|
|
@@ -15622,7 +15641,7 @@ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:f
|
|
|
15622
15641
|
import { basename as basename2, join as join5 } from "node:path";
|
|
15623
15642
|
|
|
15624
15643
|
// src/version.ts
|
|
15625
|
-
var VERSION = true ? "0.1.
|
|
15644
|
+
var VERSION = true ? "0.1.6" : "0.0.0-dev";
|
|
15626
15645
|
function osName() {
|
|
15627
15646
|
return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
|
|
15628
15647
|
}
|
|
@@ -16032,7 +16051,7 @@ async function setup() {
|
|
|
16032
16051
|
out(` \u300C${INSTRUCTION_TEXT}\u300D`);
|
|
16033
16052
|
for (const target of targets) {
|
|
16034
16053
|
const file = instructionsFileOf(target);
|
|
16035
|
-
out(` ${LABEL[target]}: ${file ?? "\
|
|
16054
|
+
out(` ${LABEL[target]}: ${file ?? "\u4F1A\u8A71\u306E\u59CB\u307E\u308A\u306Ehook\uFF08hooks.json \u306E sessionStart\uFF09\u3067\u6E21\u3057\u307E\u3059"}`);
|
|
16036
16055
|
}
|
|
16037
16056
|
const instructions = !flag("no-instructions") && (flag("yes") || !/^n(o)?$/i.test(await ask("\u8DB3\u3057\u307E\u3059\u304B\uFF1F [Y/n] ")));
|
|
16038
16057
|
const cli = installRuntime();
|
|
@@ -16067,11 +16086,6 @@ async function registerTargets() {
|
|
|
16067
16086
|
out(` ${LABEL[target]}: ${result.status === "registered" ? "\u767B\u9332\u3057\u307E\u3057\u305F" : `\u5931\u6557 \u2014 ${result.detail}`}${extra}`);
|
|
16068
16087
|
if (result.status === "failed") failed = true;
|
|
16069
16088
|
}
|
|
16070
|
-
if (flag("instructions") && targets.includes("cursor")) {
|
|
16071
|
-
out(`
|
|
16072
|
-
Cursor \u306F\u5168\u4F53\u306E\u6307\u793A\u3092\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u8AAD\u307F\u307E\u305B\u3093\u3002Cursor \u306E Settings \u2192 Rules \u2192 User Rules \u306B\u3001\u6B21\u306E\u4E00\u6587\u3092\u8CBC\u3063\u3066\u304F\u3060\u3055\u3044\u3002
|
|
16073
|
-
${INSTRUCTION_TEXT}`);
|
|
16074
|
-
}
|
|
16075
16089
|
ensureDaemon();
|
|
16076
16090
|
out("\n\u767B\u9332\u3057\u305FAI\u306F\u3001\u958B\u3044\u3066\u3044\u308B\u4F1A\u8A71\u3092\u9589\u3058\u3066\u958B\u304D\u76F4\u3059\u3068Approval Box\u3092\u4F7F\u3048\u307E\u3059\u3002");
|
|
16077
16091
|
if (failed) process.exit(1);
|
|
@@ -16127,6 +16141,7 @@ async function status() {
|
|
|
16127
16141
|
}
|
|
16128
16142
|
async function doctor() {
|
|
16129
16143
|
const problems = [];
|
|
16144
|
+
const hints = [];
|
|
16130
16145
|
const config = readConfig();
|
|
16131
16146
|
if (!config?.token) problems.push("Approval Box\u306B\u3064\u306A\u304C\u3063\u3066\u3044\u307E\u305B\u3093 \u2192 npx approval-box setup");
|
|
16132
16147
|
else {
|
|
@@ -16143,7 +16158,9 @@ async function doctor() {
|
|
|
16143
16158
|
if (!r.mcp) problems.push(`${LABEL[target]}: MCP\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093 \u2192 npx approval-box setup --only ${target}`);
|
|
16144
16159
|
if (r.hooks === false) problems.push(`${LABEL[target]}: hook\u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093 \u2192 npx approval-box setup --only ${target}`);
|
|
16145
16160
|
if (r.entry && !existsSync6(r.entry)) problems.push(`${LABEL[target]}: \u767B\u9332\u5148\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\uFF08${r.entry}\uFF09\u3002node \u3084Approval Box\u3092\u5165\u308C\u76F4\u3057\u305F\u6642\u306B\u8D77\u304D\u307E\u3059 \u2192 npx approval-box setup`);
|
|
16161
|
+
if (r.mcp && r.instructions === false) hints.push(`${LABEL[target]}: \u5168\u4F53\u306E\u6307\u793A\u306BApproval Box\u306E\u4E00\u7BC0\u304C\u3042\u308A\u307E\u305B\u3093\u3002AI\u304C\u7533\u8ACB\u3092\u51FA\u3055\u306A\u3044\u6642\u306F \u2192 npx approval-box setup --only ${target}`);
|
|
16146
16162
|
}
|
|
16163
|
+
for (const hint of hints) out(`\u30FB${hint}`);
|
|
16147
16164
|
if (!problems.length) out("\u554F\u984C\u306F\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u5C4A\u304B\u306A\u3044\u6642\u306F\u3001AI\u306B\u300CApproval Box\u306Esetup_test\u3092\u5B9F\u884C\u3057\u3066\u300D\u3068\u8A00\u3063\u3066\u3001\u3069\u3053\u3067\u6B62\u307E\u308B\u304B\u3092\u78BA\u304B\u3081\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
16148
16165
|
else for (const problem of problems) out(`\u2717 ${problem}`);
|
|
16149
16166
|
if (problems.length) process.exitCode = 1;
|
|
@@ -16165,6 +16182,13 @@ function help() {
|
|
|
16165
16182
|
npx approval-box doctor \u5C4A\u304B\u306A\u3044\u6642\u306E\u539F\u56E0\u3092\u8ABF\u3079\u308B
|
|
16166
16183
|
npx approval-box uninstall \u767B\u9332\u3092\u5168\u90E8\u5916\u3057\u3001\u3053\u306E\u7AEF\u672B\u306E\u63A5\u7D9A\u3092\u89E3\u9664\u3059\u308B`);
|
|
16167
16184
|
}
|
|
16185
|
+
async function cursorContext() {
|
|
16186
|
+
for await (const _ of process.stdin) {
|
|
16187
|
+
}
|
|
16188
|
+
out(JSON.stringify({ additional_context: `## Approval Box
|
|
16189
|
+
|
|
16190
|
+
${INSTRUCTION_TEXT}` }));
|
|
16191
|
+
}
|
|
16168
16192
|
var commands = {
|
|
16169
16193
|
setup,
|
|
16170
16194
|
test,
|
|
@@ -16173,6 +16197,7 @@ var commands = {
|
|
|
16173
16197
|
uninstall,
|
|
16174
16198
|
help,
|
|
16175
16199
|
register: registerTargets,
|
|
16200
|
+
"cursor-context": cursorContext,
|
|
16176
16201
|
mcp: runMcp,
|
|
16177
16202
|
daemon: runDaemon,
|
|
16178
16203
|
version: () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "approval-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Approval Box connector: lets Claude Code, Codex, Cursor and Grok ask you for a decision, and steers your answer back into the same session.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://approval-box.kitepon.dev",
|