approval-box 0.1.2 → 0.1.4

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.
Files changed (3) hide show
  1. package/README.md +4 -2
  2. package/dist/cli.mjs +93 -29
  3. package/package.json +9 -1
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # approval-box
2
2
 
3
- Approval Box connector. When an AI coding agent needs a human decision, it files a request to Approval Box instead of asking in chat. You answer from the Approval Box app or web, and the answer is delivered straight back into the same agent session — mid-turn if the agent is working, as a new turn if it is idle. The agent never polls.
3
+ Approval Box connector. When an AI coding agent needs a human decision, approval or action, it also files a request to Approval Box. You answer from the Approval Box app or web, and the answer is delivered straight back into the same agent session — mid-turn if the agent is working, as a new turn if it is idle. The agent never polls.
4
4
 
5
5
  Supported agents: Claude Code, Codex, Cursor, Grok — on macOS, Windows and Linux.
6
6
 
7
- AIが「人間の判断が要る」と思った時に、チャットで聞く代わりにApproval Boxへ申請します。アプリかWeb版で答えると、その答えが申請したAIの会話へそのまま届きます。
7
+ AIが人間の判断・承認・操作を求める時に、Approval Boxへも申請します。アプリかWeb版で答えると、その答えが申請したAIの会話へそのまま届きます。
8
8
 
9
9
  ## Setup / 使い方
10
10
 
@@ -14,6 +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 reads these from Settings → Rules → User Rules, so setup shows the text to paste. Skip with `--no-instructions`.
18
+ AIが毎回読む全体の指示に「判断・承認・操作が要る時は request_decision でも申請する」という一節を足すかを聞きます。Cursor は Settings → Rules → User Rules に貼る一文を案内します。足さない時は `--no-instructions`。
17
19
  2. Scan the QR code or enter the code in “Add device” in the app or web.
18
20
  画面のQRコードかコードを、アプリかWeb版の「端末を追加」で読み取ります。
19
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.
package/dist/cli.mjs CHANGED
@@ -11754,7 +11754,7 @@ var require_dist = __commonJS({
11754
11754
 
11755
11755
  // src/cli.ts
11756
11756
  var import_qrcode = __toESM(require_lib(), 1);
11757
- import { cpSync, existsSync as existsSync5, mkdirSync as mkdirSync3, rmSync as rmSync2 } from "node:fs";
11757
+ import { cpSync, existsSync as existsSync6, mkdirSync as mkdirSync4, rmSync as rmSync2 } from "node:fs";
11758
11758
  import { hostname } from "node:os";
11759
11759
  import { join as join6 } from "node:path";
11760
11760
  import { createInterface } from "node:readline/promises";
@@ -12048,9 +12048,41 @@ async function runDaemon() {
12048
12048
 
12049
12049
  // src/harness.ts
12050
12050
  import { execFileSync } from "node:child_process";
12051
- import { copyFileSync, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
12051
+ import { copyFileSync, existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
12052
12052
  import { homedir } from "node:os";
12053
- import { delimiter, dirname as dirname3, join as join4 } from "node:path";
12053
+ import { delimiter, dirname as dirname4, join as join4 } from "node:path";
12054
+
12055
+ // src/instructions.ts
12056
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
12057
+ import { dirname as dirname3 } from "node:path";
12058
+ var INSTRUCTION_TEXT = "\u30E6\u30FC\u30B6\u30FC\u306E\u5224\u65AD\u30FB\u627F\u8A8D\u30FB\u64CD\u4F5C\u304C\u5FC5\u8981\u306A\u3068\u304D\u306F\u3001\u6C7A\u88C1\u30B7\u30B9\u30C6\u30E0\u3067\u3042\u308B Approval Box \u306E request_decision \u3067\u3082\u7533\u8ACB\u3059\u308B\u3002\u3053\u308C\u3092\u4F7F\u3048\u3070\u30E6\u30FC\u30B6\u30FC\u304C\u7533\u8ACB\u306B\u6C17\u3065\u304D\u3084\u3059\u3044\u306E\u3067\u3001\u5F37\u304F\u63A8\u5968\u3059\u308B\u3002";
12059
+ var START = "<!-- approval-box:start -->";
12060
+ var END = "<!-- approval-box:end -->";
12061
+ var BLOCK = `${START}
12062
+ ## Approval Box
12063
+
12064
+ ${INSTRUCTION_TEXT}
12065
+ ${END}
12066
+ `;
12067
+ var PATTERN = new RegExp(`\\n*${START}[\\s\\S]*?${END}\\n?`, "g");
12068
+ function hasInstructions(file) {
12069
+ return existsSync3(file) && readFileSync3(file, "utf8").includes(START);
12070
+ }
12071
+ function writeInstructions(file) {
12072
+ const current = existsSync3(file) ? readFileSync3(file, "utf8").replace(PATTERN, "\n").trimEnd() : "";
12073
+ mkdirSync3(dirname3(file), { recursive: true, mode: 448 });
12074
+ writeFileSync2(file, current ? `${current}
12075
+
12076
+ ${BLOCK}` : BLOCK);
12077
+ }
12078
+ function removeInstructions(file) {
12079
+ if (!hasInstructions(file)) return;
12080
+ const rest = readFileSync3(file, "utf8").replace(PATTERN, "\n").trimEnd();
12081
+ writeFileSync2(file, rest ? `${rest}
12082
+ ` : "");
12083
+ }
12084
+
12085
+ // src/harness.ts
12054
12086
  var HARNESSES = ["claude", "codex", "cursor", "grok"];
12055
12087
  var LABEL = { claude: "Claude Code", codex: "Codex", cursor: "Cursor", grok: "Grok" };
12056
12088
  var CLIENT = { claude: "claude-code", codex: "codex", cursor: "cursor", grok: "grok" };
@@ -12065,18 +12097,24 @@ function filesOf(target) {
12065
12097
  if (target === "codex") return [join4(codexHome(), "config.toml"), join4(codexHome(), "hooks.json")];
12066
12098
  return [join4(grokDir(), "config.toml")];
12067
12099
  }
12100
+ function instructionsFileOf(target) {
12101
+ if (target === "claude") return join4(claudeDir(), "CLAUDE.md");
12102
+ if (target === "codex") return join4(codexHome(), "AGENTS.md");
12103
+ if (target === "grok") return join4(grokDir(), "AGENTS.md");
12104
+ return null;
12105
+ }
12068
12106
  function onPath(command2) {
12069
12107
  const names = process.platform === "win32" ? [`${command2}.exe`, `${command2}.cmd`, command2] : [command2];
12070
12108
  for (const dir of (process.env.PATH ?? "").split(delimiter)) {
12071
- for (const name of names) if (dir && existsSync3(join4(dir, name))) return join4(dir, name);
12109
+ for (const name of names) if (dir && existsSync4(join4(dir, name))) return join4(dir, name);
12072
12110
  }
12073
12111
  return null;
12074
12112
  }
12075
12113
  function detect(target) {
12076
- if (target === "claude") return existsSync3(claudeDir()) || !!onPath("claude");
12077
- if (target === "codex") return existsSync3(codexHome()) || !!onPath("codex");
12078
- if (target === "cursor") return existsSync3(cursorDir()) || !!onPath("cursor-agent");
12079
- return existsSync3(grokDir()) || !!onPath("grok");
12114
+ if (target === "claude") return existsSync4(claudeDir()) || !!onPath("claude");
12115
+ if (target === "codex") return existsSync4(codexHome()) || !!onPath("codex");
12116
+ if (target === "cursor") return existsSync4(cursorDir()) || !!onPath("cursor-agent");
12117
+ return existsSync4(grokDir()) || !!onPath("grok");
12080
12118
  }
12081
12119
  function stableNode() {
12082
12120
  try {
@@ -12089,7 +12127,7 @@ var CURSOR_TOOLS = ["list_my_decisions", "request_decision", "amend_decision", "
12089
12127
  var cursorCliConfig = () => join4(cursorDir(), "cli-config.json");
12090
12128
  function setCursorPermissions(enable) {
12091
12129
  const file = cursorCliConfig();
12092
- if (!existsSync3(file) && !enable) return;
12130
+ if (!existsSync4(file) && !enable) return;
12093
12131
  backupOnce(file);
12094
12132
  const current = readJson(file);
12095
12133
  const permissions = current.permissions ?? {};
@@ -12100,12 +12138,12 @@ function setCursorPermissions(enable) {
12100
12138
  }
12101
12139
  var registration = () => ({ command: stableNode(), args: [runtimeEntry("cli"), "mcp"] });
12102
12140
  function readJson(file) {
12103
- if (!existsSync3(file)) return {};
12104
- return JSON.parse(readFileSync3(file, "utf8").replace(/^/, ""));
12141
+ if (!existsSync4(file)) return {};
12142
+ return JSON.parse(readFileSync4(file, "utf8").replace(/^/, ""));
12105
12143
  }
12106
12144
  function backupOnce(file) {
12107
12145
  const copy = `${file}${PROFILE.backup_suffix}`;
12108
- if (existsSync3(file) && !existsSync3(copy)) copyFileSync(file, copy);
12146
+ if (existsSync4(file) && !existsSync4(copy)) copyFileSync(file, copy);
12109
12147
  }
12110
12148
  function setMcpJson(file, value) {
12111
12149
  backupOnce(file);
@@ -12118,7 +12156,15 @@ function setMcpJson(file, value) {
12118
12156
  async function withCodexConfig(fn) {
12119
12157
  return withCodexReceiver(PROFILE, { thread_id: "00000000-0000-4000-8000-000000000000", codex_home: codexHome() }, fn);
12120
12158
  }
12121
- async function register(target) {
12159
+ async function register(target, options = {}) {
12160
+ const file = instructionsFileOf(target);
12161
+ if (options.instructions && file) {
12162
+ try {
12163
+ writeInstructions(file);
12164
+ } catch (error) {
12165
+ return { target, status: "failed", detail: `${file}: ${error.message}` };
12166
+ }
12167
+ }
12122
12168
  const hook = (kind) => ({ command: stableNode(), script: runtimeEntry(kind) });
12123
12169
  try {
12124
12170
  if (target === "claude") {
@@ -12159,15 +12205,17 @@ async function register(target) {
12159
12205
  }
12160
12206
  async function unregister(target) {
12161
12207
  try {
12208
+ const file = instructionsFileOf(target);
12209
+ if (file) removeInstructions(file);
12162
12210
  if (target === "claude") {
12163
- if (existsSync3(claudeJson())) setMcpJson(claudeJson(), null);
12211
+ if (existsSync4(claudeJson())) setMcpJson(claudeJson(), null);
12164
12212
  removeClaudeParentHooks(PROFILE, join4(claudeDir(), "settings.json"));
12165
12213
  } else if (target === "cursor") {
12166
- if (existsSync3(join4(cursorDir(), "mcp.json"))) setMcpJson(join4(cursorDir(), "mcp.json"), null);
12214
+ if (existsSync4(join4(cursorDir(), "mcp.json"))) setMcpJson(join4(cursorDir(), "mcp.json"), null);
12167
12215
  removeCursorParentHooks(PROFILE, join4(cursorDir(), "hooks.json"));
12168
12216
  setCursorPermissions(false);
12169
12217
  } else if (target === "codex") {
12170
- if (existsSync3(join4(codexHome(), "config.toml"))) {
12218
+ if (existsSync4(join4(codexHome(), "config.toml"))) {
12171
12219
  await withCodexConfig(async (request) => {
12172
12220
  await request("config/batchWrite", { filePath: join4(codexHome(), "config.toml"), edits: [{ keyPath: `mcp_servers.${MCP_SERVER}`, value: null, mergeStrategy: "replace" }] });
12173
12221
  });
@@ -12186,6 +12234,10 @@ async function unregister(target) {
12186
12234
  }
12187
12235
  }
12188
12236
  function registered(target) {
12237
+ const file = instructionsFileOf(target);
12238
+ return { ...registeredTools(target), instructions: file ? hasInstructions(file) : null };
12239
+ }
12240
+ function registeredTools(target) {
12189
12241
  const entryOf = (value) => (value?.args ?? [])[0];
12190
12242
  if (target === "claude") {
12191
12243
  const entry = readJson(claudeJson()).mcpServers?.[MCP_SERVER];
@@ -12199,10 +12251,10 @@ function registered(target) {
12199
12251
  return { mcp: !!entry, hooks: cursorParentHooksRegistered(PROFILE, readJson(join4(cursorDir(), "hooks.json"))), ...e ? { entry: e } : {} };
12200
12252
  }
12201
12253
  if (target === "codex") {
12202
- const toml2 = existsSync3(join4(codexHome(), "config.toml")) ? readFileSync3(join4(codexHome(), "config.toml"), "utf8") : "";
12254
+ const toml2 = existsSync4(join4(codexHome(), "config.toml")) ? readFileSync4(join4(codexHome(), "config.toml"), "utf8") : "";
12203
12255
  return { mcp: toml2.includes(`[mcp_servers.${MCP_SERVER}]`), hooks: null };
12204
12256
  }
12205
- const toml = existsSync3(join4(grokDir(), "config.toml")) ? readFileSync3(join4(grokDir(), "config.toml"), "utf8") : "";
12257
+ const toml = existsSync4(join4(grokDir(), "config.toml")) ? readFileSync4(join4(grokDir(), "config.toml"), "utf8") : "";
12206
12258
  return { mcp: toml.includes(MCP_SERVER), hooks: null };
12207
12259
  }
12208
12260
 
@@ -15566,11 +15618,11 @@ var StdioServerTransport = class {
15566
15618
  };
15567
15619
 
15568
15620
  // src/mcp.ts
15569
- import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
15621
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
15570
15622
  import { basename as basename2, join as join5 } from "node:path";
15571
15623
 
15572
15624
  // src/version.ts
15573
- var VERSION = true ? "0.1.2" : "0.0.0-dev";
15625
+ var VERSION = true ? "0.1.4" : "0.0.0-dev";
15574
15626
  function osName() {
15575
15627
  return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
15576
15628
  }
@@ -15586,7 +15638,7 @@ function harnessOf(clientName) {
15586
15638
  return "other";
15587
15639
  }
15588
15640
  var INSTRUCTIONS = [
15589
- "Approval Box\u306F\u3001\u5229\u7528\u8005\uFF08\u4EBA\u9593\uFF09\u306E\u5224\u65AD\u304C\u8981\u308B\u6642\u306B\u4F7F\u3046\u3002\u30C1\u30E3\u30C3\u30C8\u3067\u805E\u304B\u305A\u306B request_decision \u3067\u7533\u8ACB\u3059\u308B\u3002\u7B54\u3048\u306F\u5229\u7528\u8005\u304C\u30B9\u30DE\u30DB\u3084Web\u3067\u51FA\u3057\u3001\u3053\u306E\u4F1A\u8A71\u3078\u81EA\u52D5\u3067\u5C4A\u304F\u3002",
15641
+ "Approval Box\u306F\u3001\u5229\u7528\u8005\uFF08\u4EBA\u9593\uFF09\u306E\u5224\u65AD\u30FB\u627F\u8A8D\u30FB\u64CD\u4F5C\u304C\u8981\u308B\u6642\u306B\u4F7F\u3046\u3002URL\u3092\u958B\u3044\u3066\u306E\u627F\u8A8D\u3084\u3001\u5229\u7528\u8005\u306E\u624B\u3067\u884C\u3046\u4F5C\u696D\u3092\u983C\u3080\u6642\u3082\u542B\u3080\u3002\u305D\u306E\u6642\u306F request_decision \u3067\u3082\u7533\u8ACB\u3059\u308B\u3002\u5229\u7528\u8005\u304C\u7533\u8ACB\u306B\u6C17\u3065\u304D\u3084\u3059\u3044\u306E\u3067\u3001\u5F37\u304F\u63A8\u5968\u3059\u308B\u3002\u7B54\u3048\u306F\u5229\u7528\u8005\u304C\u30B9\u30DE\u30DB\u3084Web\u3067\u51FA\u3057\u3001\u3053\u306E\u4F1A\u8A71\u3078\u81EA\u52D5\u3067\u5C4A\u304F\u3002",
15590
15642
  "\u7533\u8ACB\u306E\u524D\u306B\u5FC5\u305A list_my_decisions \u3067\u81EA\u5206\u306E\u7533\u8ACB\u3092\u898B\u308B\u3002\u540C\u3058\u4EF6\u304C\u672A\u6C7A\u30FB\u4FDD\u7559\u306B\u3042\u308C\u3070\u65B0\u3057\u304F\u51FA\u3055\u306A\u3044\u3002\u5185\u5BB9\u304C\u5909\u308F\u3063\u305F\u306A\u3089 amend_decision\u3001\u8981\u3089\u306A\u304F\u306A\u3063\u305F\u306A\u3089 cancel_decision\u3002\u7B54\u3048\u304C\u51FA\u3066\u3044\u308C\u3070\u3001\u305D\u306E\u7B54\u3048\u306B\u5F93\u3046\u3002\u307E\u3060\u7121\u3044\u4EF6\u3060\u3051\u3092 request_decision \u3067\u7533\u8ACB\u3059\u308B\u3002",
15591
15643
  "\u7533\u8ACB\u3057\u305F\u3089\u7B54\u3048\u3092\u5F85\u3063\u3066\u4F55\u5EA6\u3082\u547C\u3070\u306A\u3044\u3002\u7B54\u3048\u306F\u5C4A\u304F\u306E\u3067\u3001\u4ED6\u306E\u4F5C\u696D\u3092\u7D9A\u3051\u308B\u304B\u30BF\u30FC\u30F3\u3092\u7D42\u3048\u3066\u3088\u3044\u3002",
15592
15644
  "\u5229\u7528\u8005\u306B\u300CApproval Box\u306Esetup_test\u3092\u5B9F\u884C\u3057\u3066\u300D\u3068\u8A00\u308F\u308C\u305F\u3089 setup_test \u3092\u547C\u3076\u3002\u5C4A\u3044\u305F\u7B54\u3048\u306B\u66F8\u304B\u308C\u305F\u78BA\u8A8D\u30B3\u30FC\u30C9\u3067 confirm_setup_test \u3092\u547C\u3076\u3002"
@@ -15669,7 +15721,7 @@ var processChannels = /* @__PURE__ */ new Map();
15669
15721
  var lastChannel;
15670
15722
  function savedParents() {
15671
15723
  try {
15672
- return existsSync4(parentsFile()) ? JSON.parse(readFileSync4(parentsFile(), "utf8")) : {};
15724
+ return existsSync5(parentsFile()) ? JSON.parse(readFileSync5(parentsFile(), "utf8")) : {};
15673
15725
  } catch {
15674
15726
  return {};
15675
15727
  }
@@ -15895,7 +15947,7 @@ function installRuntime() {
15895
15947
  const target = join6(home(), "runtime", VERSION);
15896
15948
  if (runtimeDir() !== target) {
15897
15949
  rmSync2(target, { recursive: true, force: true });
15898
- mkdirSync3(target, { recursive: true });
15950
+ mkdirSync4(target, { recursive: true });
15899
15951
  cpSync(runtimeDir(), target, { recursive: true });
15900
15952
  }
15901
15953
  return join6(target, "cli.mjs");
@@ -15976,6 +16028,13 @@ async function setup() {
15976
16028
  out("\u3084\u3081\u307E\u3057\u305F\u3002");
15977
16029
  return;
15978
16030
  }
16031
+ out("\nAI\u304C\u6BCE\u56DE\u8AAD\u3080\u5168\u4F53\u306E\u6307\u793A\u306B\u3001\u6B21\u306E\u4E00\u7BC0\u3092\u8DB3\u3059\u3068\u3001AI\u304CApproval Box\u3092\u4F7F\u3046\u3088\u3046\u306B\u306A\u308A\u307E\u3059\uFF08\u5916\u3059\u6642\u306F uninstall\uFF09\u3002");
16032
+ out(` \u300C${INSTRUCTION_TEXT}\u300D`);
16033
+ for (const target of targets) {
16034
+ const file = instructionsFileOf(target);
16035
+ out(` ${LABEL[target]}: ${file ?? "\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u306F\u8AAD\u307E\u306A\u3044\u305F\u3081\u3001\u767B\u9332\u5F8C\u306B\u8CBC\u308B\u5834\u6240\u3092\u6848\u5185\u3057\u307E\u3059"}`);
16036
+ }
16037
+ const instructions = !flag("no-instructions") && (flag("yes") || !/^n(o)?$/i.test(await ask("\u8DB3\u3057\u307E\u3059\u304B\uFF1F [Y/n] ")));
15979
16038
  const cli = installRuntime();
15980
16039
  const token = option("token") ?? (config?.server === server ? config?.token : void 0);
15981
16040
  let connection;
@@ -15993,7 +16052,7 @@ async function setup() {
15993
16052
  throw error;
15994
16053
  }
15995
16054
  const { spawnSync } = await import("node:child_process");
15996
- const result = spawnSync(process.execPath, [cli, "register", "--targets", targets.join(",")], { stdio: "inherit" });
16055
+ const result = spawnSync(process.execPath, [cli, "register", "--targets", targets.join(","), ...instructions ? ["--instructions"] : []], { stdio: "inherit" });
15997
16056
  if (result.status !== 0) throw new Error("AI\u3078\u306E\u767B\u9332\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002");
15998
16057
  await api.call("PUT", "/connection/clients", { clients: targets.map((t) => CLIENT[t]), os: osName() });
15999
16058
  if (flag("no-test")) return;
@@ -16003,11 +16062,16 @@ async function registerTargets() {
16003
16062
  const targets = (option("targets") ?? "").split(",").filter(Boolean);
16004
16063
  let failed = false;
16005
16064
  for (const target of targets) {
16006
- const result = await register(target);
16065
+ const result = await register(target, { instructions: flag("instructions") });
16007
16066
  const extra = result.steer ? `\uFF08${STEER_LABEL[result.steer.split(":")[0] ?? ""] ?? `\u4F5C\u696D\u4E2D\u306E\u5272\u308A\u8FBC\u307F: ${result.steer}`}\uFF09` : "";
16008
16067
  out(` ${LABEL[target]}: ${result.status === "registered" ? "\u767B\u9332\u3057\u307E\u3057\u305F" : `\u5931\u6557 \u2014 ${result.detail}`}${extra}`);
16009
16068
  if (result.status === "failed") failed = true;
16010
16069
  }
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
+ }
16011
16075
  ensureDaemon();
16012
16076
  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");
16013
16077
  if (failed) process.exit(1);
@@ -16056,7 +16120,7 @@ async function status() {
16056
16120
  for (const target of HARNESSES) {
16057
16121
  if (!detect(target)) continue;
16058
16122
  const r = registered(target);
16059
- out(` ${LABEL[target]}: MCP ${r.mcp ? "\u767B\u9332\u6E08\u307F" : "\u672A\u767B\u9332"}${r.hooks === null ? "" : ` / hook ${r.hooks ? "\u767B\u9332\u6E08\u307F" : "\u672A\u767B\u9332"}`}`);
16123
+ out(` ${LABEL[target]}: MCP ${r.mcp ? "\u767B\u9332\u6E08\u307F" : "\u672A\u767B\u9332"}${r.hooks === null ? "" : ` / hook ${r.hooks ? "\u767B\u9332\u6E08\u307F" : "\u672A\u767B\u9332"}`}${r.instructions === null ? "" : ` / \u6307\u793A ${r.instructions ? "\u3042\u308A" : "\u306A\u3057"}`}`);
16060
16124
  }
16061
16125
  const d = daemonStatus();
16062
16126
  out(`\u914D\u9001\u30C7\u30FC\u30E2\u30F3: ${d.running ? `\u52D5\u4F5C\u4E2D\uFF08pid ${d.pid}\uFF09` : "\u505C\u6B62\u4E2D\uFF08\u6B21\u306E\u7533\u8ACB\u3067\u8D77\u52D5\u3057\u307E\u3059\uFF09"}`);
@@ -16072,13 +16136,13 @@ async function doctor() {
16072
16136
  problems.push(error instanceof ServerError && error.status === 401 ? "\u3053\u306E\u7AEF\u672B\u306E\u63A5\u7D9A\u304C\u5916\u3055\u308C\u3066\u3044\u307E\u3059 \u2192 npx approval-box setup" : `\u30B5\u30FC\u30D0\u30FC\u306B\u3064\u306A\u304C\u308A\u307E\u305B\u3093: ${error.message}`);
16073
16137
  }
16074
16138
  }
16075
- if (!existsSync5(process.execPath)) problems.push(`node \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\uFF08${process.execPath}\uFF09`);
16139
+ if (!existsSync6(process.execPath)) problems.push(`node \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\uFF08${process.execPath}\uFF09`);
16076
16140
  for (const target of HARNESSES) {
16077
16141
  if (!detect(target)) continue;
16078
16142
  const r = registered(target);
16079
16143
  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}`);
16080
16144
  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}`);
16081
- if (r.entry && !existsSync5(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`);
16145
+ 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`);
16082
16146
  }
16083
16147
  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");
16084
16148
  else for (const problem of problems) out(`\u2717 ${problem}`);
@@ -16094,7 +16158,7 @@ async function test() {
16094
16158
  function help() {
16095
16159
  out(`Approval Box ${VERSION}
16096
16160
 
16097
- npx approval-box setup [--server URL] [--token TOKEN] [--only claude,codex,cursor,grok] [--yes]
16161
+ npx approval-box setup [--server URL] [--token TOKEN] [--only claude,codex,cursor,grok] [--no-instructions] [--yes]
16098
16162
  AI\u306BApproval Box\u3092\u767B\u9332\u3057\u3001\u3053\u306E\u7AEF\u672B\u3092\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u7D50\u3073\u3001\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u78BA\u8A8D\u307E\u3067\u884C\u3046
16099
16163
  npx approval-box test \u63A5\u7D9A\u30C6\u30B9\u30C8\uFF08AI\u306B\u300CApproval Box\u306Esetup_test\u3092\u5B9F\u884C\u3057\u3066\u300D\u3068\u8A00\u3063\u3066\u78BA\u304B\u3081\u308B\uFF09
16100
16164
  npx approval-box status \u3064\u306A\u304C\u308A\u3001\u767B\u9332\u3001\u78BA\u8A8D\u306E\u72B6\u614B
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "approval-box",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
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",
@@ -41,5 +41,13 @@
41
41
  },
42
42
  "engines": {
43
43
  "node": ">=20"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/kitepon/approval-box.git",
48
+ "directory": "packages/connector"
49
+ },
50
+ "bugs": {
51
+ "url": "https://github.com/kitepon/approval-box/issues"
44
52
  }
45
53
  }