Skip to content
Open
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
28 changes: 15 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,20 @@ Claude Code ──(生命周期 hook)──► octopus-hook.js ──HTTP POST /

> **「Claude 客户端消息」**指的是 Claude Code(CLI agent)的回复内容——`Stop` 时从 transcript 抽最后一段 assistant 文本(截断 + 密钥脱敏),对应桌宠的 `💬` 气泡。(不是 Claude 桌面聊天 App 的消息。)

### 🛰️ Codex 后端(零配置、只读
### 🛰️ Codex 后端(官方 hooks + 只读回退

除 Claude Code 外,桌宠也能盯 [OpenAI Codex](https://github.com/openai/codex)(CLI / Desktop):

```
Codex CLI / Desktop ──写 rollout──► ~/.codex/sessions/YYYY/MM/DD/*.jsonl
│ (codex-watch 增量 tail,只读)
同一个会话状态机 (core, agentId: 'codex') ──► 桌宠/面板
Codex CLI / Desktop ──官方生命周期 hooks──► octopus-hook.js ──► /state
└─旧版 rollout JSONL──► codex-watch(只读回退/计量)──┘
同一个会话状态机 (core, agentId: 'codex') ──► 桌宠/面板
```

- **不装任何钩子**:Codex 只有一个全局 `notify` 配置位(常被 ChatGPT 桌面 App 占用),所以走「监听 rollout 文件」——增量 tail、零配置、卸载无残留。
- 事件映射:`user_message→思考`;首个 `exec_command/apply_patch` 后整轮保持“干活中”(工具结果和中间 reasoning 不会误降成思考),直到 `task_complete→完成庆祝+💬` 或 `turn_aborted→中断徽标`;`token_count→上下文%`。guardian / auto-review 等 subagent 内部线程自动过滤,长会话恢复时只读取新增事件、不重放历史。
- **新版实时通道**:首次启动会合并写入 `~/.codex/hooks.json`,注册 `SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Stop …`。其他程序的 hooks 保留不动;托盘“卸载钩子”也只删除 LLMPET 条目并先备份。Codex 若提示新 hook 待审核,请在 Codex 中运行 `/hooks` 并信任 LLMPET 的 `octopus-hook.js` 命令。
- **旧版兼容回退**:仍增量 tail `~/.codex/sessions/**/*.jsonl`。hooks 与 rollout 同时报告时会跨来源去重;长会话恢复只读新增事件,不重放历史。
- 事件映射:`UserPromptSubmit→思考`;`PreToolUse/PostToolUse→干活中`;`Stop→完成庆祝+💬`;`PermissionRequest→等待处理`。guardian / auto-review 等 subagent rollout 仍自动过滤。
- **用量与额度分开**:按 rollout 每条 `last_token_usage` 建立去重台账,显示今日 / 本机留存历史 token;套餐 5h 主窗口与周窗口仍单独读取 `rate_limits`。本地 token 台账不冒充 OpenAI 账单或账号全生命周期统计。
- **两种形态**(托盘 → 设置 → 分身):
- **单宠**(默认):一只宠同时盯两个后端,会话列表用图标区分(Claude 橙 burst / Codex 蓝终端块);
Expand Down Expand Up @@ -104,7 +105,7 @@ Codex CLI / Desktop ──写 rollout──► ~/.codex/sessions/YYYY/MM/DD/*.js
git clone https://github.com/myunwang/LLMPET.git
cd LLMPET
npm ci # 按 package-lock.json 安装(国内网络慢可加:ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ npm ci)
npm start # 启动桌宠(首次启动会注册 Claude Code 钩子)
npm start # 启动桌宠(首次启动会注册 Claude Code / Codex 钩子)
```

启动后新开的 Claude Code / Codex 会话会被感知;近期仍活跃的 Codex rollout 也会静默恢复到会话列表。右键桌宠可切三款皮肤和单宠/双宠模式。
Expand All @@ -115,17 +116,17 @@ npm start # 启动桌宠(首次启动会注册 Claude Code 钩子
- 终端归属解析(pid 链)首次约 1–2s(起一次 PowerShell),之后按会话缓存在 `~/.octopus/pidwalk-cache.json`,热路径无感。
- 打包安装版:`npm run package:win`(electron-builder,产出 NSIS 安装包 + zip;国内网络可另设 `$env:ELECTRON_BUILDER_BINARIES_MIRROR='https://npmmirror.com/mirrors/electron-builder-binaries/'`)。

- 首次启动会把钩子写进 `~/.claude/settings.json`(合并、可逆)。之后新开的 `claude` 会话即被桌宠感知
- 首次启动会把钩子合并写进 `~/.claude/settings.json` 与 `~/.codex/hooks.json`(可逆)。Codex 若提示待审核,请运行 `/hooks` 信任 LLMPET 命令;之后新开的会话即被桌宠感知
- **左键点桌宠** = 弹出**会话列表**(状态 + 会话名 + 上下文用量%);可搜索、按 Claude / Codex / 待处理筛选、置顶或归档,点某行把对应终端 / 客户端调到前台。偏好写入 `~/.octopus/config.json`。
- 会话右侧的 **🧳** = 打开青蛙旅行:让对应 agent 在该项目中执行一次独立、只读探索,回来后展示明信片并累计成长 token。
- 会话面板底部的 **🐱 闲逛** = 打开可见 CLI,不带项目、不带任务和工具,让猫猫自己随便想想、聊聊。
- **右键** = 泡泡菜单;**拖动** = 移动位置。等授权/等回复时会**自动**弹允许/拒绝气泡。
- 托盘菜单可开详情面板、静音、唤起 Claude、打开日志、**卸载钩子**、退出。
- 托盘菜单可开详情面板、静音、唤起 Claude、打开日志、**卸载钩子**、退出。可选的“开机启动并在崩溃后恢复”默认关闭;开启后,发送失败的钩子事件会先落盘,服务恢复监听后再投递。主动点“退出”会阻止钩子复活进程,直到下次手动启动。
- 详情面板里可切皮肤 / 模式 / 设 5h 预算。
- **🥊 领地模式**(macOS):右键桌宠点“巡视”可立即扫描并执行一次;托盘可开启“自动巡逻”,开启后立即首巡、随后定时轮询(默认关)。两条定律:①**猫爪在上**——检测到别的桌面宠物(Desktop Goose / BongoCat / Shimeji 等)在跑,就把自己的窗口层级抬到最上,谁也不许压着咱(无需额外权限);②**巡视行动**——发现对方窗口,小章鱼走过去把它一步步**顶到屏幕边上**。巡视需要**辅助功能**权限(移动别人的窗口);没授权时「巡视」仍会执行猫爪在上,只是不推窗。对付 AXPosition 失效的透明窗桌宠时,会像 Computer Use 一样显示独立的橙色爪软件光标;底层兼容拖拽仍只在你**输入空闲 ≥2s** 时执行,期间隐藏系统光标,结束或异常都会补发 mouseUp 并把原光标复位,你手上有活时则静默撤退。自定义对手:`~/.octopus/config.json` 的 `territoryRivals` 数组加进程名关键词。

### 开发 / 验证开关
- `OCTOPUS_NO_HOOKS=1 npm start` —— 启动但**不动** `~/.claude/settings.json`(只验证主进程 / 界面)。
- `OCTOPUS_NO_HOOKS=1 npm start` —— 启动但**不动** Claude/Codex 的 hook 配置(只验证主进程 / 界面)。
- `OCTOPUS_ALLOW_MULTI=1 npm start` —— 跳过多实例防护(默认:实例锁 + 启动探测到别的 LLMPET 实例就退出 + 存活期间守护 `runtime.json` 不被其他副本抢走)。
- `OCTOPUS_NO_NET=1 npm start` —— **完全离线**:关掉唯一的外联请求(每 24h 拉一次 [LiteLLM 公开价目表](https://github.com/BerriAI/litellm),只下载、不上传任何本地数据),花费改用内置估算单价。
- `OCTOPUS_DEBUG=1 npm start` —— 开放 `GET /debug`(默认关闭,会暴露会话 cwd / 标题等,仅本机回环可访问)。
Expand Down Expand Up @@ -169,12 +170,13 @@ main.js Electron 主进程:窗口 / IPC / 托盘 / 启动编
preload.js 前后端唯一接口(contextBridge)
renderer/ assets/ 桌宠 + 面板的视觉与渲染
hook/
octopus-hook.js Claude Code 触发的钩子脚本(读 stdin/transcript,POST /state)
octopus-hook.js Claude Code / Codex 共用钩子脚本(读 stdin,POST /state)
backend/
transport.js 端口发现 / runtime 文件 / 标识头 / 钩子→server 传输 / node 定位
transcript.js transcript 解析(assistant 文本 / 上下文用量 / API 错误 / 标题)
pidwalk.js 进程树解析(定位会话所在终端)
hookinstall.js merge-safe 钩子安装器(合并不覆盖 / 原子写 / 卸载备份)
hookinstall.js Claude merge-safe 钩子安装器
codex-hookinstall.js Codex merge-safe 钩子安装器(原子写 / 卸载备份)
launch.js 开终端跑 claude
core.js 会话存储 + 状态机 + 快照 + 陈旧清理
server.js 本地 HTTP server(/state /permission /health)
Expand Down
17 changes: 10 additions & 7 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The interface is available in **Simplified Chinese, English, and Japanese**. Swi
- **Three skins** — Octopus 🐙, Pixel Monster 👾, and Salary Cat 🐱.
- **Patrol mode on macOS** — LLMPET can detect supported rival desktop pets, stay above them, and attempt to push their windows to the nearest screen edge.

LLMPET's state machine, metering, permission flow, process reconciliation, and desktop UI are implemented in this repository. Claude Code connects through its public hook system. Codex integration is read-only: LLMPET tails local rollout files and does not modify Codex configuration.
LLMPET's state machine, metering, permission flow, process reconciliation, and desktop UI are implemented in this repository. Claude Code and current Codex builds connect through their public hook systems; legacy Codex rollout files remain a read-only fallback and metering source.

## Salary Cat states

Expand Down Expand Up @@ -61,7 +61,7 @@ Useful commands:
npm test # full headless regression suite
npm run package:mac:dev # local ad-hoc-signed macOS package
npm run package:win # Windows installer + portable ZIP
npm run uninstall:hooks # remove LLMPET's Claude hooks safely
npm run uninstall:hooks # remove LLMPET's Claude/Codex hooks safely
```

## How the integrations work
Expand All @@ -76,13 +76,15 @@ LLMPET registers merge-safe lifecycle and permission hooks in `~/.claude/setting

### OpenAI Codex

LLMPET does not install Codex hooks. It incrementally and read-only tails:
LLMPET merge-safely registers documented lifecycle hooks in `~/.codex/hooks.json`. Other applications' handlers are preserved, and uninstall removes only LLMPET entries after making a backup. When Codex marks the new command for review, run `/hooks` and trust LLMPET's `octopus-hook.js` handler.

For older Codex builds, LLMPET still incrementally and read-only tails:

```text
~/.codex/sessions/YYYY/MM/DD/*.jsonl
```

It maps rollout events into the same state machine, filters internal subagent threads, restores long-running sessions without replaying old events, and builds a persistent local token ledger from each event's `last_token_usage`. Codex rate-limit windows remain separate; local history is not presented as an OpenAI bill.
Hook and rollout events map into the same state machine and are deduplicated across sources. The rollout fallback filters internal subagent threads, restores long-running sessions without replaying old events, and builds a persistent local token ledger from each event's `last_token_usage`. Codex rate-limit windows remain separate; local history is not presented as an OpenAI bill.

## Travel Frog

Expand Down Expand Up @@ -124,18 +126,19 @@ Patrol mode is currently macOS-only.

- The HTTP server binds only to `127.0.0.1`; write endpoints require a random per-run token in addition to loopback, Host, and browser-origin checks.
- Session data, configuration, and usage history stay on the local machine.
- Codex rollout access is read-only.
- Codex lifecycle hooks post only to LLMPET's loopback server; legacy rollout access is read-only.
- Background network access is limited to the optional daily LiteLLM pricing download. A Travel Frog run contacts Anthropic or OpenAI only after you explicitly press **Depart**; `OCTOPUS_NO_NET=1` disables LLMPET's pricing fetch, but does not override a CLI trip you explicitly start.
- Electron runs with `contextIsolation` enabled and `nodeIntegration` disabled.
- Claude hook installation is merge-safe, atomic, reversible, and backed up before uninstall.
- **Start at login and recover after crashes** is an explicit, persisted tray preference and is off by default. When enabled, a hook event that encounters a stopped app is queued locally and replayed after the recovered server starts listening. Choosing **Quit** suppresses hook recovery until the next explicit launch.

## Configuration and development flags

- `OCTOPUS_NO_HOOKS=1 npm start` — launch without changing Claude settings.
- `OCTOPUS_NO_HOOKS=1 npm start` — launch without changing Claude or Codex hook settings.
- `OCTOPUS_ALLOW_MULTI=1 npm start` — bypass single-instance protection for development.
- `OCTOPUS_NO_NET=1 npm start` — disable all external network requests.
- `OCTOPUS_DEBUG=1 npm start` — expose the local `/debug` endpoint.
- `LLMPET_NO_CODEX=1 npm start` — disable Codex rollout watching.
- `LLMPET_NO_CODEX=1 npm start` — disable Codex monitoring.
- `LLMPET_CODEX_DIR=<dir> npm start` — use a custom rollout directory for testing.

## Contributors
Expand Down
17 changes: 10 additions & 7 deletions README_JA.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ LLMPET は、**Claude Code と OpenAI Codex** の動きをひと目で確認で
- **3 種類のスキン** — タコ 🐙、ピクセルモンスター 👾、月薪喵 🐱。
- **macOS のパトロールモード** — 対応する他のデスクトップペットを検出し、最前面を維持しながら相手を画面端へ押し出します。

状態機械、利用量計測、権限処理、プロセス照合、デスクトップ UI はこのリポジトリ内で実装されています。Claude Code は公開 hook API を利用し、Codex はローカルの rollout ファイルを読み取り専用で監視します。Codex の設定は変更しません
状態機械、利用量計測、権限処理、プロセス照合、デスクトップ UI はこのリポジトリ内で実装されています。Claude Code と現在の Codex は公開 hook API を利用し、旧版 Codex rollout ファイル監視は読み取り専用のフォールバックとして残します

## 月薪喵スキンの状態

Expand Down Expand Up @@ -61,7 +61,7 @@ npm start
npm test # ヘッドレス回帰テスト一式
npm run package:mac:dev # ローカル用 ad-hoc 署名 macOS パッケージ
npm run package:win # Windows インストーラー + ZIP
npm run uninstall:hooks # LLMPET の Claude hook を安全に削除
npm run uninstall:hooks # LLMPET の Claude / Codex hook を安全に削除
```

## 連携の仕組み
Expand All @@ -76,13 +76,15 @@ LLMPET は `~/.claude/settings.json` に、既存設定と安全に共存する

### OpenAI Codex

Codex 用の hook はインストールしません。次の rollout を増分かつ読み取り専用で監視します。
LLMPET は `~/.codex/hooks.json` に公式ライフサイクル hook を既存設定と共存する形で登録します。他のアプリの hook は保持され、アンインストール時もバックアップ後に LLMPET の項目だけを削除します。Codex が新しいコマンドの確認を求めた場合は、`/hooks` を実行して LLMPET の `octopus-hook.js` を信頼してください。

旧版 Codex 向けには、次の rollout も増分かつ読み取り専用で監視します。

```text
~/.codex/sessions/YYYY/MM/DD/*.jsonl
```

rollout イベントを共通の状態機械へ変換し、内部 subagent スレッドを除外します。長時間セッションの復帰時も過去イベントを再生せず、新しく追加された部分だけを読み取ります。各イベントの `last_token_usage` から永続的なローカル token 台帳を作り、レート制限とは分けて表示します。この台帳を OpenAI の請求履歴とは表示しません。
hook と rollout のイベントは同じ状態機械へ変換し、データ源をまたいで重複排除します。rollout フォールバックは内部 subagent スレッドを除外し、長時間セッションの復帰時も過去イベントを再生しません。各イベントの `last_token_usage` から永続的なローカル token 台帳を作り、レート制限とは分けて表示します。この台帳を OpenAI の請求履歴とは表示しません。

## 旅するカエル

Expand Down Expand Up @@ -124,18 +126,19 @@ assets/memes/<meme-id>/

- HTTP サーバーは `127.0.0.1` のみにバインドし、loopback / Host / browser-origin の検証に加えて、書き込み API に起動ごとのランダム token を要求します。
- セッション情報、設定、利用履歴はローカル端末内に保存されます。
- Codex rollout へのアクセスは読み取り専用です。
- Codex lifecycle hook は LLMPET の loopback server にだけ送信し、旧版 rollout へのアクセスは読み取り専用です。
- バックグラウンド通信は、任意の LiteLLM 公開価格表の日次取得だけです。「旅するカエル」はユーザーが **出発**を押した場合にだけ Anthropic / OpenAI へ接続します。`OCTOPUS_NO_NET=1` は LLMPET の価格取得を止めますが、明示的に開始した CLI 旅行までは無効化しません。
- Electron は `contextIsolation` を有効、`nodeIntegration` を無効にしています。
- Claude hook の追加は既存設定を上書きせず、原子的かつ取り消し可能で、削除前にはバックアップを作成します。
- **ログイン時に起動し、クラッシュ後に復旧**はトレイで明示的に有効化する永続設定で、既定では無効です。有効時に停止中のアプリへ届いた hook イベントはローカルへ待避され、復旧した server の listen 後に再送されます。**終了**を選ぶと、次回の明示的な起動まで hook による復活を抑止します。

## 設定・開発用フラグ

- `OCTOPUS_NO_HOOKS=1 npm start` — Claude 設定を変更せずに起動します。
- `OCTOPUS_NO_HOOKS=1 npm start` — Claude / Codex の hook 設定を変更せずに起動します。
- `OCTOPUS_ALLOW_MULTI=1 npm start` — 開発時に単一インスタンス制限を無効化します。
- `OCTOPUS_NO_NET=1 npm start` — 外部ネットワーク通信を無効化します。
- `OCTOPUS_DEBUG=1 npm start` — ローカル `/debug` エンドポイントを有効化します。
- `LLMPET_NO_CODEX=1 npm start` — Codex rollout の監視を無効化します。
- `LLMPET_NO_CODEX=1 npm start` — Codex の監視を無効化します。
- `LLMPET_CODEX_DIR=<dir> npm start` — テスト用の rollout ディレクトリを指定します。

## コントリビューター
Expand Down
1 change: 1 addition & 0 deletions backend/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ function activityToEvents(act) {
out.push({ kind: 'say', text: clip(plainText(session.assistantLastOutput), 280), emotion: emo, project, ts: Date.now() });
}
break;
case 'PermissionRequest':
case 'Notification':
case 'Elicitation':
out.push({
Expand Down
Loading