Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Publish to npm

on:
workflow_dispatch:
inputs:
version:
description: Package version already merged into main
required: true
type: string

permissions:
contents: read
id-token: write

concurrency:
group: npm-publish
cancel-in-progress: false

jobs:
publish:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
fetch-depth: 0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: '24'
registry-url: https://registry.npmjs.org
package-manager-cache: false
- name: Verify requested version
env:
EXPECTED_VERSION: ${{ inputs.version }}
run: |
node -e 'const version = require("./package.json").version; if (version !== process.env.EXPECTED_VERSION) throw new Error(`Expected ${process.env.EXPECTED_VERSION}, got ${version}`)'
- run: npm ci --no-audit --no-fund
- run: npm run verify:release-commit
- run: npm publish --provenance
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ agent-neutral coreのadapterであり、detector、reporting、stateをhost別
path正規化と実行体探索は`paths.mjs`に置く。
- host依存の決定点は`src/host/adapters.mjs`だけが所有する。host固有実装は専用moduleへ閉じ、
業務ロジックへ`process.platform`やhost別分岐を散らさない。
- Claude、Codex、Cursorのtool DBはhost-localかつ別fileで所有し、一方のrefreshで他方を
- Claude、Codex、Cursor、Grokのtool DBはhost-localかつ別fileで所有し、一方のrefreshで他方を
pruneまたはoverwriteしない。global DBはdescription cacheだけで、audit入力へ混ぜない。

### 再帰安全
Expand Down Expand Up @@ -87,7 +87,7 @@ daemon lifecycleはapp-level heartbeatとUserPromptSubmit auto-resurrectを使
- Claude呼出しはsession-scoped、preamble-once、schema失敗時のsession renewを使う。
- 隔離workdir `~/.spotter/workdir/`へ`CLAUDE.md`を置かない。
- Claudeは`.spotter/tool-db.json`、Codexは`.spotter/tool-db.codex.json`、Cursorは
`.spotter/tool-db.cursor.json`だけを監査入力にする。
`.spotter/tool-db.cursor.json`、Grokは`.spotter/tool-db.grok.json`だけを監査入力にする。

公開CLI、hook / daemon IPC、runtime error store、evaluation、dashboardの現行contractとtest対応表は
[docs/02_spotter-claude-contract.md](docs/02_spotter-claude-contract.md)を正とする。未解決事項は
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
各節はそのversion公開時点の変更記録であり、後続versionにより置換された仕様を含む。
現行runtime契約は[`docs/00_overview.md`](https://github.com/kitepon/Spotter/blob/main/docs/00_overview.md)から辿る。

## 1.8.0 — 2026-09-27

- Grok Buildのnative hookとhost専用カタログを追加。Linux、macOS、Windows nativeの実セッションで入力時・応答後の監査を確認した。Grok 1.0.41は受動hookのstdoutを会話へ渡さないため、findingは構造eventと評価DBに記録する。
- Grokのheadless実行で最終応答つき`Stop`が欠けたturnを`SessionEnd`で補完する。Windowsでは`SessionStart`のカタログ更新完了を待ち、初回監査から有効なツールを使う。
- Windows Cursorのhook入力に付くUTF-8 BOMを受け付け、Git管理外のprojectでもCodex CLI監査を実行できるようにする。
- dashboardの現行構成から廃止済みFOX WSL2端末を外し、3端末を表示する。

## 1.7.3 — 2026-09-24

- 退役するcodex-sidecarの明示CLI、追加監査dispatch、primary auditor backend指定、診断と関連コードを削除する。Jev、Codex CLI、Haikuの主監査は維持する。
Expand Down
26 changes: 19 additions & 7 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

## 所有境界

本repositoryはSpotter製品面の全体、すなわち監査挙動、Claude/Codex hook adapter、
本repositoryはSpotter製品面の全体、すなわち監査挙動、Claude/Codex/Cursor/Grok hook adapter、
project marker、catalog discoveryとhost-local tool DB、評価store、dashboard server、
diagnostics、installer、release packagingを所有します。
[dotagents](https://github.com/kitepon/dotagents)が所有するのは共有agent指示と、
Expand Down Expand Up @@ -68,16 +68,18 @@ cd your-project
spotter install
```

macOS の Homebrew Node 環境では、Codex hook command の Node パスに現在の実体と一致する
macOS の Homebrew Node 環境では、CodexとGrokのhook commandのNodeパスに現在の実体と一致する
安定 symlink (`/opt/homebrew/bin/node`) を使います。
`/opt/homebrew/Cellar/node/<version>/...` のような version 固定パスを書かないため、
Homebrew で Node が更新されても Codex hook が古い Node パスに取り残されません。
Homebrew で Node が更新されてもhookが古いNodeパスに取り残されません。

`v0.3.0` 以降は**プロジェクト単位の明示的 install** を採用しています (v0.2 までの `postinstall` 自動登録はデーモン増殖の主因だったため撤回)。各プロジェクトの `.claude/settings.json` に hook を登録し、そのプロジェクトでの Claude Code セッションのみで有効になります。
Codex CLI が使える環境では、同じ `spotter install` が user-level の Codex native hooks も登録します。実際に動くプロジェクトは `spotter install` が作る `.spotter/marker.json` で制限されるため、無関係な Codex セッションでは Spotter は起動しません。
Codex 側では現行の `[features].hooks = true` を有効化し、互換のため旧 `codex_hooks` diagnostics output も認識します。
Spotter が所有する Codex handler は現行の同期 command schema で生成します。install / upgrade 後は `/hooks` で review して新しい Codex session を開いてください。`spotter codex-hook diagnostics` は登録と readiness を診断しますが、trust を内部状態から推測しません。

Grok Buildがある環境では、`spotter install`はGrok native hookも登録し、専用の`.spotter/tool-db.grok.json`を初期化します。入力時と応答後の監査結果は`.spotter/hook-events.jsonl`と評価DBに残ります。Grok 1.0.41は受動hookのstdoutを会話へ渡さないため、findingは親会話には表示されません。登録は`spotter grok-hook diagnostics`で確認し、install後は新しいGrok sessionを開いてください。

Spotter を upgrade した後、release note で hook 設定変更が案内されている場合は、各 install 済みプロジェクトで `spotter install` を再実行してください。global package update でコード経路は変わりますが、既存 `.claude/settings.json` の timeout 値は自動では書き換わりません。

```bash
Expand All @@ -88,12 +90,20 @@ spotter uninstall # このプロジェクトの hook 登録を解除

```bash
npm uninstall -g claude-spotter
npm install -g claude-spotter
npm install -g claude-spotter@1.8.0
spotter --version
spotter install -y
spotter codex-hook install
```

公開担当は検証済みcommitを`main`へmergeし、`main`から
[Publish to npm](https://github.com/kitepon/Spotter/actions/workflows/publish.yml)へpackage versionを指定して実行します。
workflowは指定versionと`main`への着地を検査してから`npm publish`します。
初回だけ[npm packageのAccess設定](https://www.npmjs.com/package/claude-spotter/access)で
GitHub ActionsのTrusted Publisherを登録してください。ownerは`kitepon`、repositoryは`Spotter`、
workflow filenameは`publish.yml`、environmentは空欄、直接の`npm publish`を許可します。
GitHubが管理するrunnerのOIDCを使うため、以降の公開にnpm tokenの保存やCLIログインは要りません。
公開後はregistryのversionを確認し、対象端末へそのversionを指定してインストールします。

## 動作要件

- **Node.js 22.13 以上**(npmの`engines.node`と同じ)
Expand Down Expand Up @@ -249,6 +259,8 @@ spotter codex-hook install
# Codex native hooks の修復 / 明示登録 (通常は spotter install が実行)
spotter codex-hook diagnostics
# Codex hook の登録/readiness を診断。trust は /hooks で review
spotter grok-hook diagnostics
# Grok native監査hookの登録を確認
spotter auditor model-matrix --fixtures test/fixtures/auditor-model-matrix.v2.json --recent-turns 2 --body-cap 600
# pinned auditor model profile を再現可能に比較する experimental eval
spotter uninstall # hook 登録を解除 (~/.spotter は残す)
Expand All @@ -271,7 +283,7 @@ project/tool内訳、非採用case、監査対象request、任意の提案時Thr
health確認は端末一覧request時だけなので、端末がofflineでもbackground監視や
retry queueを作らず、その端末だけを切り離せる。

4端末のservice、reverse tunnel、Caddy/Cloudflare構成は
3端末のservice、reverse tunnel、Caddy/Cloudflare構成は
[docs/11_dashboard-operations.md](https://github.com/kitepon/Spotter/blob/main/docs/11_dashboard-operations.md)を参照。
Windows同梱のTask Scheduler installerはnpm・SSH用の対話ユーザープロファイルを維持しつつ、
dashboardの2つのPowerShell actionを非対話・console非表示で起動する。
Expand Down Expand Up @@ -326,7 +338,7 @@ profile から production へ自動昇格しません。`latest` alias や
- **失敗は声に出して縮退、hostを固めない** (v1.4.15) — この版でbackend failureによるpromptのsilent消去を止めた。v1.4.19以降もnon-blocking挙動は維持し、旧model可視警告文は固定`systemMessage`・stderr・構造event診断へ置換した
- **プラグイン形式の MCP サーバー対応** — `plugin:everything-claude-code:context7` のように名前に内部コロンを含むサーバーを正しくパースし、配下のツールをカタログに取り込めるようになった (旧版はこの形式のサーバーをすべて単一の `"plugin"` に潰して、Claude の監査から silent に脱落させていた)
- **プロジェクト単位の監査隔離** — daemon が監査に使うのはローカル DB のみ。グローバル DB は description 再利用キャッシュに役割限定。**他プロジェクト**でインストールしたツールが現プロジェクトの監査に混入することはない
- **手放しでカタログ維持** — `spotter install` が Claude DB を自動 seed、Claude / Codex それぞれの SessionStart が host-local DB を bg refresh する。手書き管理は一切不要
- **手放しでカタログ維持** — `spotter install`が利用可能なhostのDBを作る。Claude / Codex / CursorはSessionStartでバックグラウンド更新し、Grokは初回監査前に更新完了を待つ
- **Codex native hooks** — Codex host は primary auditor backend として Codex CLI を使い、`.spotter/tool-db.codex.json` を Claude DB と分離し、backend failure は Haiku fallback ではなく明示 error として扱う
- **監査対象** — ユーザー追加分 (MCP / スキル / サブエージェント) のみ。Claude Code 本体側のツールは意図的に対象外 (Claude は元から自発率が高いため)
- **実装規範** — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止 ([AGENTS.md §0](https://github.com/kitepon/Spotter/blob/main/AGENTS.md))
Expand Down
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Built and maintained by [Quo](https://x.com/QLyun35332) at [kitepon.dev](https:/
## Ownership boundary

This repository owns the complete Spotter product surface: auditor behavior,
Claude/Codex hook adapters, project markers, catalog discovery and host-local
Claude/Codex/Cursor/Grok hook adapters, project markers, catalog discovery and host-local
tool databases, evaluation storage, dashboard servers, diagnostics, installers,
and release packaging. [dotagents](https://github.com/kitepon/dotagents)
owns shared agent instructions and the optional factory-reporter configuration
Expand Down Expand Up @@ -69,16 +69,18 @@ cd your-project
spotter install
```

On macOS with Homebrew Node, Codex hook commands use the stable
On macOS with Homebrew Node, Codex and Grok hook commands use the stable
`/opt/homebrew/bin/node` symlink when it resolves to the current Node binary,
instead of a versioned `/opt/homebrew/Cellar/node/<version>/...` path. That keeps
Codex hooks working across Homebrew Node upgrades.
both sets of hooks working across Homebrew Node upgrades.

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.
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.
For Codex, install enables the current `[features].hooks = true` flag and still recognizes older `codex_hooks` diagnostics output for compatibility.
Installer-owned Codex handlers use the current synchronous command schema. After install or upgrade, review them with `/hooks`, then open a fresh Codex session; `spotter codex-hook diagnostics` reports registration/readiness but does not guess hook trust.

When Grok Build is installed, `spotter install` also registers native Grok hooks and seeds a separate `.spotter/tool-db.grok.json`. Grok prompt and final-response audits write findings to `.spotter/hook-events.jsonl` and the evaluation database. Grok 1.0.41 ignores stdout from passive hooks, so it does not show those findings in the parent conversation. Check registration with `spotter grok-hook diagnostics` and open a new Grok session after install.

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.

```bash
Expand All @@ -89,12 +91,20 @@ Release install smoke:

```bash
npm uninstall -g claude-spotter
npm install -g claude-spotter
npm install -g claude-spotter@1.8.0
spotter --version
spotter install -y
spotter codex-hook install
```

Maintainer release: merge the tested release commit into `main`, then run
[Publish to npm](https://github.com/kitepon/Spotter/actions/workflows/publish.yml) from `main` with the package version.
The workflow checks the requested version and the `main` ancestry gate before `npm publish`.
For the one-time npm setup, open the [package access settings](https://www.npmjs.com/package/claude-spotter/access)
and add a GitHub Actions trusted publisher: owner `kitepon`, repository `Spotter`,
workflow filename `publish.yml`, no environment, and allow direct `npm publish`.
The GitHub-hosted workflow uses OIDC, so later releases need no stored npm token or CLI login.
After publication, verify the registry version and install that exact version on each target host.

## Requirements

- **Node.js 22.13+**
Expand Down Expand Up @@ -253,6 +263,8 @@ spotter codex-hook install
# repair / explicitly register Codex native hooks (normally handled by spotter install)
spotter codex-hook diagnostics
# check Codex hook registration/readiness; trust is reviewed with /hooks
spotter grok-hook diagnostics
# check Grok native audit hook registration
spotter auditor model-matrix --fixtures test/fixtures/auditor-model-matrix.v2.json --recent-turns 2 --body-cap 600
# experimental reproducible comparison of pinned auditor model profiles
spotter uninstall # remove hooks from this project (leaves ~/.spotter intact)
Expand All @@ -278,7 +290,7 @@ audited by Spotter, and optional proposal-time Throughline evidence. The hub che
when the device list is requested, so an offline terminal is isolated without a background monitor
or retry queue.

The reference four-terminal service, reverse-tunnel, and Caddy/Cloudflare layout is documented in
The reference three-terminal service, reverse-tunnel, and Caddy/Cloudflare layout is documented in
[docs/11_dashboard-operations.md](https://github.com/kitepon/Spotter/blob/main/docs/11_dashboard-operations.md).
On Windows, the bundled Task Scheduler installer keeps the interactive user's profile for npm and
SSH while starting both dashboard PowerShell actions non-interactively with hidden console windows.
Expand Down Expand Up @@ -349,7 +361,7 @@ the production values for controlled experiments; diagnostics mark overrides as
- **Failures degrade loudly, never freeze the host** (v1.4.15) — this release stopped backend failure from silently erasing a prompt. Since v1.4.19, the non-blocking behavior remains but the old model-visible warning text is replaced by fixed `systemMessage`, stderr, and structured event diagnostics
- **Plugin-scoped MCP servers** — names like `plugin:everything-claude-code:context7` (with internal colons) are now parsed correctly and their tools enter the catalog. Earlier versions silently collapsed all plugin MCP servers into a single literal `"plugin"`, dropping their tools from Claude's audit
- **Per-project / per-host audit isolation** — the daemon audits against the local DB only; global DBs are host-specific description caches. Tools discovered in *other* projects or another host can never bleed into this project's audit set
- **Zero-touch catalog** — `spotter install` seeds the Claude DB automatically; Claude and Codex SessionStart hooks keep their host-local DBs fresh in the background. You never have to maintain the tool list by hand
- **Zero-touch catalog** — `spotter install` seeds each available host's DB. Claude, Codex, and Cursor refresh in the background; Grok waits for refresh before its first audit
- **Codex native hooks** — Codex host uses Codex CLI as the primary auditor backend, keeps a separate `.spotter/tool-db.codex.json`, and surfaces backend failures explicitly instead of falling back to Haiku
- **Audit scope** — only user-added surface (MCP servers / skills / sub-agents). Claude Code's built-in tools are intentionally out of scope; Claude already uses those reliably
- **Implementation invariants** — no fallbacks, no silent failures, no provisional code (see [§0 in AGENTS.md](https://github.com/kitepon/Spotter/blob/main/AGENTS.md))
Expand Down
6 changes: 6 additions & 0 deletions bin/spotter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { runStatus } from '../src/cli/status.mjs';
import { runDbList, runDbRefresh, runDbRebuild } from '../src/cli/db-cmd.mjs';
import { runCodexHookCommand } from '../src/cli/codex-hook-cmd.mjs';
import { runCursorHookCommand } from '../src/cli/cursor-hook-cmd.mjs';
import { runGrokHookCommand } from '../src/cli/grok-hook-cmd.mjs';
import { runAuditorCommand } from '../src/cli/auditor-cmd.mjs';
import { runDiagnosticsCommand } from '../src/cli/diagnostics-cmd.mjs';
import { runEvaluationCommand } from '../src/cli/evaluation-cmd.mjs';
Expand Down Expand Up @@ -65,6 +66,8 @@ Usage:
(experimental) manage Codex native hooks
spotter cursor-hook install|uninstall|diagnostics
manage Cursor native catalog-refresh hooks
spotter grok-hook install|uninstall|diagnostics
manage Grok native audit hooks
spotter auditor judge --stage STAGE --input FILE
(experimental) run primary auditor backend once
spotter auditor matrix --stage STAGE --input FILE
Expand Down Expand Up @@ -127,6 +130,9 @@ async function main() {
case 'cursor-hook':
await runCursorHookCommand({ argv: rest });
return;
case 'grok-hook':
await runGrokHookCommand({ argv: rest });
return;
case 'auditor':
await runAuditorCommand({ argv: rest });
return;
Expand Down
Loading
Loading