claude-spotter 1.4.0 → 1.4.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.2
4
+
5
+ **既存 project の hook command path を npm global 版へ更新する patch release**。v1.4.1 の `spotter install` は Codex hooks を自動登録するようになったが、既存 `.claude/settings.json` に `spotter.mjs` hook がある場合、登録済み判定で timeout だけ更新し、command path を現在の package root へ差し替えていなかった。local checkout 由来の hook が残ると、global npm update 後も古い checkout を呼び続け得るため修正。
6
+
7
+ ### 変更点
8
+
9
+ - **編集 [src/cli/install.mjs](src/cli/install.mjs)**: 既存 Spotter hook を見つけた場合も `hook.command` を現在の `SPOTTER_BIN` に更新する。これにより `npm install -g claude-spotter` 後、各プロジェクトで `spotter install` を再実行すれば hook は global npm 版へ揃う
10
+ - **編集 [test/install.test.mjs](test/install.test.mjs)**: 古い `/old/bin/spotter.mjs` hook が `spotter install` で現在の package path に差し替わる回帰テストを追加
11
+
12
+ ### ユーザー側で必要な手順
13
+
14
+ 1. `npm install -g claude-spotter@1.4.2`
15
+ 2. 各プロジェクトで `spotter install`
16
+
17
+ ## 1.4.1
18
+
19
+ **Codex native hooks の有効化手順を `spotter install` に集約する patch release**。v1.4.0 は npm publish まで成功したが、Codex hooks を使うには `spotter codex-hook install` が別手順として残っていた。完成条件を「global npm install 後、各プロジェクトで `spotter install` する以外の手作業を不要にする」と再定義し、Codex CLI がある環境では `spotter install` が Codex hooks も idempotent に登録するようにした。
20
+
21
+ ### 変更点
22
+
23
+ - **編集 [src/cli/install.mjs](src/cli/install.mjs)**: project install 時に Codex CLI (`codex --version`) を検出し、存在する場合は `installCodexHooks()` を呼んで `~/.codex/hooks.json` と `[features].codex_hooks = true` を更新する。Codex CLI が無い環境では明示メッセージを出して Codex hooks 登録だけを行わない
24
+ - **編集 [test/install.test.mjs](test/install.test.mjs)**: `spotter install` が Codex CLI presence 時に Codex hooks を登録する回帰テストを追加。既存 refresh 系テストは実ユーザー `~/.codex` を触らないよう DI で固定
25
+ - **編集 README / README.ja / postinstall / CLAUDE.md / open issues**: インストール手順を `npm install -g claude-spotter` → 各プロジェクトで `spotter install` に集約。`spotter codex-hook install` は修復 / 明示登録用 command として残す
26
+
27
+ ### ユーザー側で必要な手順
28
+
29
+ 1. `npm install -g claude-spotter@1.4.1` で global update
30
+ 2. 各プロジェクトで `spotter install` を実行する。Claude hooks、`.spotter/marker.json`、Claude catalog seed が設定され、Codex CLI がある環境では Codex native hooks も登録される
31
+
3
32
  ## 1.4.0
4
33
 
5
34
  **Codex native hooks を npm 配布可能な完成状態へ昇格する minor bump**。`npm install -g claude-spotter@1.4.0` で `spotter` CLI を global install し、各プロジェクトでは `spotter install`、Codex を使う場合は追加で `spotter codex-hook install` を実行するだけで動く状態にした。手書き tool list や install 時の Codex seed は不要で、Codex 側 catalog は SessionStart hook が自動更新する。
package/README.ja.md CHANGED
@@ -41,12 +41,10 @@ Spotter が拾うのは、たとえばこういう瞬間です。
41
41
  npm install -g claude-spotter
42
42
  cd your-project
43
43
  spotter install
44
- # 任意: Codex native hooks を使う場合
45
- spotter codex-hook install
46
44
  ```
47
45
 
48
46
  `v0.3.0` 以降は**プロジェクト単位の明示的 install** を採用しています (v0.2 までの `postinstall` 自動登録はデーモン増殖の主因だったため撤回)。各プロジェクトの `.claude/settings.json` に hook を登録し、そのプロジェクトでの Claude Code セッションのみで有効になります。
49
- Codex 対応は `spotter codex-hook install` で別途有効化します。Codex hook は user-level に登録されますが、実際に動くプロジェクトは `spotter install` が作る `.spotter/marker.json` で制限されます。
47
+ Codex CLI が使える環境では、同じ `spotter install` user-level Codex native hooks も登録します。実際に動くプロジェクトは `spotter install` が作る `.spotter/marker.json` で制限されるため、無関係な Codex セッションでは Spotter は起動しません。
50
48
 
51
49
  Spotter を upgrade した後、release note で hook 設定変更が案内されている場合は、各 install 済みプロジェクトで `spotter install` を再実行してください。global package update でコード経路は変わりますが、既存 `.claude/settings.json` の timeout 値は自動では書き換わりません。
52
50
 
@@ -105,7 +103,7 @@ flowchart LR
105
103
 
106
104
  監査対象のツール (name + description) は host-local に分離されます。Claude は `<project>/.spotter/tool-db.json`、Codex は `<project>/.spotter/tool-db.codex.json` を使います。**daemon が監査に使うのは Claude local DB のみ**で、Codex native hooks は Codex local DB を読みます。グローバル DB `~/.spotter/tool-db.json` は他プロジェクトでの description 再利用キャッシュとしてのみ機能し、監査入力には混ぜません。各 host-local DB は **その host の現時点の discovery 結果と一致** (refresh 時に prune される) するため、別プロジェクトや別 host のツールリストで上書きされることはありません。
107
105
 
108
- **`spotter install` が Claude catalog の初回 seed を自動実行し、Claude Code セッション起動ごとに SessionStart hook が bg で `spotter db refresh` を走らせる**ため、Claude 通常運用で手動コマンドを叩く必要はありません。Codex native hooks も同じ考え方で、`spotter codex-hook install` が Codex `SessionStart` hook を登録し、Codex セッション開始時に `spotter db refresh --host-agent codex` を bg 起動して `.spotter/tool-db.codex.json` を更新します。Claude catalog には書き込みません。Claude discovery は `claude mcp list` と Claude skills / sub-agents、Codex discovery は `codex mcp list/get` と Codex skills を読むため、両 host の利用可能ツール差分を別 DB として保持できます。各 MCP サーバーの `tools/list` は JSON-RPC で取得 (HTTP / SSE / stdio transport 対応)、スキルとサブエージェントは frontmatter から直接抽出、claude.ai baseline (OAuth proxy 経由の Gmail / Calendar / Drive 25 件) は Claude 側でのみ `claude mcp list` に該当サーバーが存在する環境で注入されます。**手書きでツールリストを管理する必要はありません**。
106
+ **`spotter install` が Claude catalog の初回 seed を自動実行し、Claude Code セッション起動ごとに SessionStart hook が bg で `spotter db refresh` を走らせる**ため、Claude 通常運用で手動コマンドを叩く必要はありません。Codex CLI が使える環境では、同じ `spotter install` が Codex native hooks も登録します。Codex `SessionStart` hook `spotter db refresh --host-agent codex` を bg 起動して `.spotter/tool-db.codex.json` を更新します。Claude catalog には書き込みません。Claude discovery は `claude mcp list` と Claude skills / sub-agents、Codex discovery は `codex mcp list/get` と Codex skills を読むため、両 host の利用可能ツール差分を別 DB として保持できます。各 MCP サーバーの `tools/list` は JSON-RPC で取得 (HTTP / SSE / stdio transport 対応)、スキルとサブエージェントは frontmatter から直接抽出、claude.ai baseline (OAuth proxy 経由の Gmail / Calendar / Drive 25 件) は Claude 側でのみ `claude mcp list` に該当サーバーが存在する環境で注入されます。**手書きでツールリストを管理する必要はありません**。
109
107
 
110
108
  ## Throughline との関係
111
109
 
@@ -142,7 +140,7 @@ spotter codex work --findings findings.json --instruction "docs 更新" --approv
142
140
  --allowed-path docs/ --preserve-worktree
143
141
  # 承認済み codex-sidecar work を isolated worktree で実行
144
142
  spotter codex-hook install
145
- # Codex native SessionStart / UserPromptSubmit / Stop hook を登録
143
+ # Codex native hooks の修復 / 明示登録 (通常は spotter install が実行)
146
144
  spotter codex-hook diagnostics
147
145
  # Codex hooks feature と Spotter hook 登録を診断
148
146
  spotter uninstall # hook 登録を解除 (~/.spotter は残す)
package/README.md CHANGED
@@ -41,12 +41,10 @@ Spotter audits in two stages:
41
41
  npm install -g claude-spotter
42
42
  cd your-project
43
43
  spotter install
44
- # Optional, for Codex native hooks:
45
- spotter codex-hook install
46
44
  ```
47
45
 
48
46
  Since `v0.3.0`, Spotter requires **explicit per-project install** (the earlier `postinstall` auto-registration was the leading cause of orphan daemons). `spotter install` writes hooks into the project's `.claude/settings.json`; the audit is then active only in Claude Code sessions for that project.
49
- Codex support is enabled separately by `spotter codex-hook install`, which writes user-level Codex hooks; project activation still depends on the same per-project `.spotter/marker.json` created by `spotter install`.
47
+ When the Codex CLI is available, the same `spotter install` also registers user-level Codex native hooks. Project activation still depends on the same per-project `.spotter/marker.json`, so unrelated Codex sessions do not trigger Spotter.
50
48
 
51
49
  After upgrading Spotter, re-run `spotter install` in each installed project when release notes mention hook setting changes. The global package update changes the code path, but existing `.claude/settings.json` timeout values are not rewritten automatically.
52
50
 
@@ -105,7 +103,7 @@ flowchart LR
105
103
 
106
104
  The audited catalog is host-local: Claude uses `<project>/.spotter/tool-db.json`, while Codex uses `<project>/.spotter/tool-db.codex.json`. **The daemon audits against the Claude local DB only**, and Codex native hooks read the Codex local DB. The global DB at `~/.spotter/tool-db.json` is a description-reuse cache shared across projects, not an audit source. Each host-local DB matches that host's **current** discovery snapshot for the project (stale entries are pruned on refresh), so tools from another project or another host cannot overwrite this session's audit catalog.
107
105
 
108
- **`spotter install` seeds the Claude catalog automatically, and the SessionStart hook runs a background `spotter db refresh` on every Claude Code session start** — so you don't need to invoke Claude catalog commands by hand. Codex native hooks do the same for Codex: `spotter codex-hook install` registers a Codex `SessionStart` hook that starts `spotter db refresh --host-agent codex` in the background, updating `.spotter/tool-db.codex.json` without touching the Claude catalog. Claude discovery reads `claude mcp list` plus Claude skills / sub-agents; Codex discovery reads `codex mcp list/get` plus Codex skills. Each MCP server's `tools/list` is fetched via JSON-RPC (HTTP / SSE / stdio transports supported); skill and sub-agent metadata comes straight from frontmatter; the claude.ai baseline (25 hand-curated entries for Gmail / Calendar / Drive over OAuth proxy) is injected only for Claude when `claude mcp list` confirms the server is present. **You never have to maintain the tool list by hand.**
106
+ **`spotter install` seeds the Claude catalog automatically, and the SessionStart hook runs a background `spotter db refresh` on every Claude Code session start** — so you don't need to invoke Claude catalog commands by hand. When Codex CLI is available, the same `spotter install` registers Codex native hooks; their `SessionStart` hook starts `spotter db refresh --host-agent codex` in the background, updating `.spotter/tool-db.codex.json` without touching the Claude catalog. Claude discovery reads `claude mcp list` plus Claude skills / sub-agents; Codex discovery reads `codex mcp list/get` plus Codex skills. Each MCP server's `tools/list` is fetched via JSON-RPC (HTTP / SSE / stdio transports supported); skill and sub-agent metadata comes straight from frontmatter; the claude.ai baseline (25 hand-curated entries for Gmail / Calendar / Drive over OAuth proxy) is injected only for Claude when `claude mcp list` confirms the server is present. **You never have to maintain the tool list by hand.**
109
107
 
110
108
  ## Spotter and Throughline
111
109
 
@@ -143,7 +141,7 @@ spotter codex work --findings findings.json --instruction "Update docs" --approv
143
141
  --allowed-path docs/ --preserve-worktree
144
142
  # run approved codex-sidecar work in an isolated worktree
145
143
  spotter codex-hook install
146
- # register Codex native SessionStart / UserPromptSubmit / Stop hooks
144
+ # repair / explicitly register Codex native hooks (normally handled by spotter install)
147
145
  spotter codex-hook diagnostics
148
146
  # check Codex hooks feature and Spotter hook entries
149
147
  spotter uninstall # remove hooks from this project (leaves ~/.spotter intact)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-spotter",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Audit agent running alongside Claude Code that catches missed tool calls — 気づく役と実行する役の分離",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,7 +27,7 @@
27
27
  "license": "MIT",
28
28
  "repository": {
29
29
  "type": "git",
30
- "url": "https://github.com/kitepon-rgb/Spotter.git"
30
+ "url": "git+https://github.com/kitepon-rgb/Spotter.git"
31
31
  },
32
32
  "bugs": {
33
33
  "url": "https://github.com/kitepon-rgb/Spotter/issues"
@@ -27,6 +27,5 @@ console.log(' cd <your-project>');
27
27
  console.log(' spotter install');
28
28
  console.log(' This writes hooks to <project>/.claude/settings.json and a .spotter/');
29
29
  console.log(' marker so unrelated `claude -p` invocations do not trigger Spotter.');
30
- console.log(' Optional for Codex native hooks:');
31
- console.log(' spotter codex-hook install');
30
+ console.log(' If Codex CLI is installed, `spotter install` also registers Codex hooks.');
32
31
  console.log(' Codex hooks refresh .spotter/tool-db.codex.json on SessionStart.');
@@ -1,4 +1,5 @@
1
- // `spotter install` — create ~/.spotter/, register hooks in .claude/settings.json.
1
+ // `spotter install` — create ~/.spotter/, register Claude hooks, and register
2
+ // Codex native hooks when the Codex CLI is available.
2
3
  //
3
4
  // Per plan §15.4, this shows a diff and asks for confirmation before touching settings.json.
4
5
  //
@@ -12,6 +13,7 @@
12
13
  // has no projectRoot so DB seeding is skipped there).
13
14
 
14
15
  import { mkdir, writeFile, readFile, access } from 'node:fs/promises';
16
+ import { spawnSync } from 'node:child_process';
15
17
  import { homedir } from 'node:os';
16
18
  import { join, resolve, dirname } from 'node:path';
17
19
  import { fileURLToPath } from 'node:url';
@@ -19,6 +21,7 @@ import { createInterface } from 'node:readline/promises';
19
21
  import { version as SPOTTER_VERSION } from '../version.mjs';
20
22
  import { refresh } from '../tool-db/refresh.mjs';
21
23
  import { localDbPath, globalDbPath } from '../tool-db/loader.mjs';
24
+ import { installCodexHooks } from './codex-hook-cmd.mjs';
22
25
 
23
26
  const HERE = dirname(fileURLToPath(import.meta.url));
24
27
  const PACKAGE_ROOT = resolve(HERE, '..', '..');
@@ -45,7 +48,16 @@ const HOOK_EVENTS = [
45
48
  { event: 'SessionEnd', sub: 'session-end', timeout: 3 },
46
49
  ];
47
50
 
48
- export async function runInstall({ target = 'project', autoYes = false, cwd = process.cwd(), skipRefresh = false, refreshFn = refresh } = {}) {
51
+ export async function runInstall({
52
+ target = 'project',
53
+ autoYes = false,
54
+ cwd = process.cwd(),
55
+ skipRefresh = false,
56
+ skipCodexHooks = skipRefresh,
57
+ refreshFn = refresh,
58
+ codexCliPresentFn = isCodexCliPresent,
59
+ installCodexHooksFn = installCodexHooks,
60
+ } = {}) {
49
61
  const settingsPath = target === 'user'
50
62
  ? join(homedir(), '.claude', 'settings.json')
51
63
  : join(cwd, '.claude', 'settings.json');
@@ -108,6 +120,16 @@ export async function runInstall({ target = 'project', autoYes = false, cwd = pr
108
120
  console.log(`wrote ${settingsPath}`);
109
121
  }
110
122
 
123
+ if (target === 'project' && !skipCodexHooks) {
124
+ if (codexCliPresentFn()) {
125
+ const result = await installCodexHooksFn();
126
+ console.log(' Codex hooks registered');
127
+ console.log(` Codex hooks: ${result.hooksPath}`);
128
+ } else {
129
+ console.log(' Codex CLI not found — Codex hooks not registered');
130
+ }
131
+ }
132
+
111
133
  // Seed the tool-db so the first session has something to audit against.
112
134
  // Runs regardless of whether settings.json changed — re-running `spotter install`
113
135
  // on an already-installed project is the canonical way to refresh tool-db drift
@@ -134,6 +156,7 @@ export async function runInstall({ target = 'project', autoYes = false, cwd = pr
134
156
 
135
157
  console.log('\nnext steps:');
136
158
  console.log(' reload Claude Code (or open a new session) to activate Spotter');
159
+ console.log(' open a new Codex session to activate Codex hooks when Codex CLI is installed');
137
160
  }
138
161
 
139
162
  async function exists(path) {
@@ -145,6 +168,16 @@ async function exists(path) {
145
168
  }
146
169
  }
147
170
 
171
+ function isCodexCliPresent() {
172
+ const result = spawnSync('codex', ['--version'], {
173
+ encoding: 'utf8',
174
+ stdio: ['ignore', 'pipe', 'pipe'],
175
+ timeout: 5_000,
176
+ windowsHide: true,
177
+ });
178
+ return result.status === 0;
179
+ }
180
+
148
181
  async function loadSettings(path) {
149
182
  try {
150
183
  const raw = await readFile(path, 'utf8');
@@ -171,6 +204,7 @@ function mergeHooks(current) {
171
204
  if (hook?.type !== 'command') continue;
172
205
  if (!hook.command?.includes('spotter.mjs') || !hook.command?.includes(`hook ${sub}`)) continue;
173
206
  alreadyHas = true;
207
+ hook.command = command;
174
208
  hook.timeout = timeout;
175
209
  }
176
210
  }