{"_id":"@bloret-crew/crewrouter-helper","_rev":"6-2e8751c3ae1c820ae02bc611ba8b3873","name":"@bloret-crew/crewrouter-helper","dist-tags":{"latest":"1.0.5"},"versions":{"1.0.0":{"name":"@bloret-crew/crewrouter-helper","version":"1.0.0","keywords":["crewrouter","claude-code","codex","grok","hooks","oauth","cli"],"license":"MIT","_id":"@bloret-crew/crewrouter-helper@1.0.0","maintainers":[{"name":"rhedar","email":"rhedarliu@outlook.com"}],"bin":{"crewrouter-helper":"bin/cli.js"},"dist":{"shasum":"47415bd94289b24ed1fe4db97e78ae1f672c64c1","tarball":"https://registry.npmjs.org/@bloret-crew/crewrouter-helper/-/crewrouter-helper-1.0.0.tgz","fileCount":8,"integrity":"sha512-82KJUqbn1APwQfSx2K7homHJBraZTBNh1rG9izRuo5HR87V0KffYlldLUnUajwnKoDW9omYrFdpgXhesr8w+kw==","signatures":[{"sig":"MEQCIEcyH8QFR//f7Vffc7k0YbR5fnSniC6BUv1rHSjE+iOxAiAOkZ8ZcvDeO2qeGVI8UKnCfu580x82wtzbnDjfp/5ZTA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33708},"engines":{"node":">=18"},"gitHead":"0e4f8dc619b9b5551bb3d13f28865757fc08d082","_npmUser":{"name":"rhedar","email":"rhedarliu@outlook.com"},"_npmVersion":"11.16.0","description":"CrewRouter 客户端事件统一上报器（Node.js 零依赖 CLI）：hook / emit / watch / login / logout / test / --print","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/crewrouter-helper_1.0.0_1787665957224_0.8636804861648522","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@bloret-crew/crewrouter-helper","version":"1.0.1","keywords":["crewrouter","claude-code","codex","grok","hooks","oauth","cli"],"license":"MIT","_id":"@bloret-crew/crewrouter-helper@1.0.1","maintainers":[{"name":"rhedar","email":"rhedarliu@outlook.com"}],"bin":{"crewrouter-helper":"bin/cli.js"},"dist":{"shasum":"2025f87d05885ea23ec5683db2c7ff06da88269d","tarball":"https://registry.npmjs.org/@bloret-crew/crewrouter-helper/-/crewrouter-helper-1.0.1.tgz","fileCount":8,"integrity":"sha512-RxRWwX92/Kc3sKnVbH3PJsqriaEc3iYhxPahjIDvmy4TAEfTlcOocXCQ/I+KJfZqn9nBd99Btkfbz9TjHwCAvA==","signatures":[{"sig":"MEUCIELw3HnPj8mVbbQbwIdykCg7V7X02evIXJOjlwI6OhG/AiEA+e/T48PLHN/MwhZs5yZEcWWV9DQq4EfeGVQdnQpE1eI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIHSyPV+cK8LwDlM1KbVtzClf5rdDDcjvJH32yen/RaS7AiBW5//JCO6hNcS3V6P1zz4LdGUMdx/RjJJzq1Rpy6f1LQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35914},"engines":{"node":">=18"},"gitHead":"e811b1ac7c90daff0cbe80494373d2dbf147373e","_npmUser":{"name":"rhedar","email":"rhedarliu@outlook.com"},"_npmVersion":"11.16.0","description":"CrewRouter 客户端事件统一上报器（Node.js 零依赖 CLI）：hook / emit / watch / login / logout / test / --print","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/crewrouter-helper_1.0.1_1787926234058_0.5212817455984635","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@bloret-crew/crewrouter-helper","version":"1.0.2","keywords":["crewrouter","claude-code","codex","grok","hooks","oauth","cli"],"license":"GPL-3.0-only","_id":"@bloret-crew/crewrouter-helper@1.0.2","maintainers":[{"name":"rhedar","email":"rhedarliu@outlook.com"}],"bin":{"crewrouter-helper":"bin/cli.js"},"dist":{"shasum":"a378d3964858cd48cd5ceab5ebd32a9728fb13dd","tarball":"https://registry.npmjs.org/@bloret-crew/crewrouter-helper/-/crewrouter-helper-1.0.2.tgz","fileCount":9,"integrity":"sha512-TY7t7z5swXcZoftunhphfzNLKcTWgS1zASYzUJq58A4oqCMDHMzN/gcbTJ5ExcVocgqAOzdYjvUZ52rQC2YWUg==","signatures":[{"sig":"MEUCIQCk+x/sCbpW7br7uSQ+eog5/HZ34jCsVznikf2Pc60zywIgLOYWe/UEMUmSFKD52/UHc7YCxi2ntlhshsO4XXY7JbM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDD38rXiaKNiMUmEFMmy2Tb+oSfZ8vPRdjOAAwVijRVjwIgdpAmEr2GQVbtN09GWdYIt9vfN/BIpiOxfUtsQIMKqo8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76384},"engines":{"node":">=18"},"gitHead":"713c57428900a138f1fb315496ef66523abf8069","_npmUser":{"name":"rhedar","email":"rhedarliu@outlook.com"},"_npmVersion":"11.16.0","description":"CrewRouter 客户端事件统一上报器（Node.js 零依赖 CLI，含交互式 TUI）：hook / emit / watch / login / logout / test / --print","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/crewrouter-helper_1.0.2_1787928458837_0.9501521469330354","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@bloret-crew/crewrouter-helper","version":"1.0.3","keywords":["crewrouter","claude-code","codex","grok","hooks","oauth","cli"],"license":"GPL-3.0-only","_id":"@bloret-crew/crewrouter-helper@1.0.3","maintainers":[{"name":"rhedar","email":"rhedarliu@outlook.com"}],"bin":{"crewrouter-helper":"bin/cli.js"},"dist":{"shasum":"1fbbb4293cbdbe340f901aedca72e55dd79e0f96","tarball":"https://registry.npmjs.org/@bloret-crew/crewrouter-helper/-/crewrouter-helper-1.0.3.tgz","fileCount":9,"integrity":"sha512-rxU906rgN6PhjCdgl8F2dfpZ8yXq0/Zt4JSEq5p0BFRNVuSZ+zCE2vTHzkCvBH2hwtsDsmW4/dZqcr+PbkDTdQ==","signatures":[{"sig":"MEYCIQCDvM9iu7iJK2sijJmyGOfdWbp3c5VXxxLAElFGhu9gxgIhAIzJTusKftzLMczM/rZYCmKmMSe3R+6+kX0hSqNgxfTr","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDi6yfFa5VP1Y9hfYodQjejUGSrDBFf8ycXkGzyzhcJVQIgT4G8WVD2vR8/iAMXSei+ENdOGJ7sAlpy4s/rL3Oaih0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":77938},"engines":{"node":">=18"},"gitHead":"57594bbed780ee4dc8bdc3aca4e45e6d04d858e5","_npmUser":{"name":"rhedar","email":"rhedarliu@outlook.com"},"_npmVersion":"11.16.0","description":"CrewRouter 客户端事件统一上报器（Node.js 零依赖 CLI，含交互式 TUI）：hook / emit / watch / login / logout / test / --print","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/crewrouter-helper_1.0.3_1787928945525_0.5405264966476715","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@bloret-crew/crewrouter-helper","version":"1.0.4","keywords":["crewrouter","claude-code","codex","grok","hooks","oauth","cli"],"license":"GPL-3.0-only","_id":"@bloret-crew/crewrouter-helper@1.0.4","maintainers":[{"name":"rhedar","email":"rhedarliu@outlook.com"}],"bin":{"crewrouter-helper":"bin/cli.js"},"dist":{"shasum":"a389d6e6db9ceceba31d8a600d53525ca0cc9b31","tarball":"https://registry.npmjs.org/@bloret-crew/crewrouter-helper/-/crewrouter-helper-1.0.4.tgz","fileCount":9,"integrity":"sha512-Ei6KyOr0Bdv/grxJK5j0Fh7G6xIeCLfwJxZGnY/asFtilozx2GJ+L9Yy8dyZSnaHs8+WX+WMrczsJ/Ynxaoyfw==","signatures":[{"sig":"MEUCIQCXHnAZUx771ZD5E9DeXMWbnE8NBdqundqm1qsBi1XVHwIgVtDi2LhdoQQ+3u4nb6jmxXZZhvzlOP3ydcwL2CewGgI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC+SuKKMxOyyfFW0FP8aBz9sw1kIE5WFME8UcwjvNvVRgIhALzQcbRfvrNtdTEN97NOto0soJ6riA9L0HTL3inJ9Ra+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":78652},"engines":{"node":">=18"},"gitHead":"88912e9b06855da862ab5ac52220c609ab4e8056","_npmUser":{"name":"rhedar","email":"rhedarliu@outlook.com"},"_npmVersion":"11.16.0","description":"CrewRouter 客户端事件统一上报器（Node.js 零依赖 CLI，含交互式 TUI）：hook / emit / watch / login / logout / test / --print","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/crewrouter-helper_1.0.4_1787929486108_0.4351698282212191","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"_id":"@bloret-crew/crewrouter-helper@1.0.5","bin":{"crewrouter-helper":"bin/cli.js"},"dist":{"shasum":"f56a1aa77dd4aca318e7b057184d5ea50c099e31","tarball":"https://registry.npmjs.org/@bloret-crew/crewrouter-helper/-/crewrouter-helper-1.0.5.tgz","fileCount":9,"integrity":"sha512-5uWfwGgwGISpSGHIgc2pmM3QvKHQ1aKg0dXm8oYruBeEbmTA42p617v6PtFSpDN+MUBiwnrAzVzd3xXZHVNdaw==","signatures":[{"sig":"MEQCIEHDZvxkW6fAwFAUFPdk+MAC+pbYNilswBJDQ+YQ5pZJAiBvaDfQyYOnZMgP4bFX5U6SXjUvFT0Pe4QCvohWPDo+pg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICYKfBZhArBf3oxRTPvSjMhj7M6rSKc0wdRBfu1tgWxuAiEAjSHmXpsgGCJ+67SlqkRXDJ4zKO5zR2k4yGFlW5z0FRU="}],"unpackedSize":78653},"name":"@bloret-crew/crewrouter-helper","engines":{"node":">=18"},"gitHead":"e23c8d4b8fff6904e111f9c7871f4d8e0731ee18","license":"GPL-3.0-only","version":"1.0.5","_npmUser":{"name":"rhedar","email":"rhedarliu@outlook.com"},"keywords":["crewrouter","claude-code","codex","grok","hooks","oauth","cli"],"_npmVersion":"11.16.0","description":"CrewRouter 客户端事件统一上报器（Node.js 零依赖 CLI，含交互式 TUI）：hook / emit / watch / login / logout / test / --print","directories":{},"maintainers":[{"name":"rhedar","email":"rhedarliu@outlook.com"}],"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/crewrouter-helper_1.0.5_1787963076566_0.5559122093868176"}}},"time":{"created":"2026-08-25T13:52:36.947Z","modified":"2026-08-29T00:24:36.831Z","1.0.0":"2026-08-25T13:52:37.381Z","1.0.1":"2026-08-28T14:10:34.173Z","1.0.2":"2026-08-28T14:47:38.929Z","1.0.3":"2026-08-28T14:55:45.653Z","1.0.4":"2026-08-28T15:04:46.179Z","1.0.5":"2026-08-29T00:24:36.665Z"},"license":"GPL-3.0-only","keywords":["crewrouter","claude-code","codex","grok","hooks","oauth","cli"],"description":"CrewRouter 客户端事件统一上报器（Node.js 零依赖 CLI，含交互式 TUI）：hook / emit / watch / login / logout / test / --print","maintainers":[{"name":"rhedar","email":"rhedarliu@outlook.com"}],"readme":"# crewrouter-helper（@bloret-crew/crewrouter-helper）\n\nCrewRouter 客户端事件统一上报器 —— Node.js 零依赖 CLI，所有 AI 客户端共用这一个程序。\n\nCrewRouter is a unified event reporting tool for the client – ​​a Node.js-based CLI with zero dependencies, shared by all AI clients.\n\n## 安装 / Install\n\n```bash\nnpm i -g @bloret-crew/crewrouter-helper\n# 或免安装直接运行 / or run without installing\nnpx @bloret-crew/crewrouter-helper test\n\n# 要求 / Requires: Node.js >= 18；零第三方依赖 / zero third-party dependencies\n```\n\n## 交互式 TUI\n\n在交互式终端直接运行 `crewrouter-helper`，即可打开菜单：查看连接状态、登录/配置服务、为 Claude Code / Qwen Code / Codex 写入上报 Hook，以及发送测试事件。菜单使用方向键选择、Enter 确认，`q` 或 Esc 返回；同时支持 `j/k` 作为备用导航键。客户端配置会保留已有内容，重复配置不会重复添加 Hook。当前包保持 Node.js 18+ 零依赖设计。\n\n客户端配置入口会自动写入：Claude Code 的 `~/.claude/settings.json`、Qwen Code 的 `~/.qwen/settings.json`、Codex 的 `~/.codex/config.toml`。非交互环境仍显示原有帮助信息，适合脚本和 Hook 调用。\n\n## 子命令 / Subcommands\n\n| 命令 / Command | 说明 / Description |\n| --- | --- |\n| `hook --harness <id> [--event <type>]` | 读 stdin 的 Claude 风格 hook JSON，映射后转发 / Read Claude-style hook JSON from stdin and forward it |\n| `emit --harness <id> --event <t> [--session <id>] [--tool <n>] [--cwd <dir>]` | 直接发一条事件 / Emit one event directly |\n| `watch [--harness grok] [--interval 5]` | 常驻 tail `~/.grok/sessions/**/updates.jsonl` / Tail Grok session updates |\n| `login [--url http://127.0.0.1:20003]` | 浏览器 OAuth PKCE 授权 / Browser OAuth PKCE login |\n| `logout` | 删除本地凭证 / Remove local credentials |\n| `test [--harness hermes]` | 发测试事件验证链路 / Send a test event |\n| `--print` | 输出有效 access token（临期自动刷新）/ Print a valid access token (auto-refreshes) |\n\n事件取值 / Events: `session_start`、`session_end`、`tool_use`\nharness 取值 / Harness ids: `claude_code` / `codex` / `grok` / `opencode` /\n`qwen_code` / `hermes` / `openclaw` / `deepseek_harness`\n\n## 登录与凭证 / Login & credentials\n\n```bash\ncrewrouter-helper login                                  # 打开官方商店，选择已登录过的 CrewRouter 后授权\ncrewrouter-helper login --url http://127.0.0.1:20003   # 直接在指定 CrewRouter 授权\ncrewrouter-helper test                                  # 应输出 HTTP 200 {\"ok\":true}\ncrewrouter-helper logout                                # 删除 ~/.config/cr-report.json\n```\n\n配置文件 `~/.config/cr-report.json` 兼容两种形态 / The config file supports both shapes:\n\n```jsonc\n// OAuth（推荐 / recommended）\n{ \"url\": \"http://127.0.0.1:20003\", \"access_token\": \"...\", \"refresh_token\": \"...\", \"expires_at\": 1234567890.0 }\n// 静态 Key（仍兼容 / still supported）\n{ \"url\": \"http://127.0.0.1:20003\", \"key\": \"cr-sk-...\" }\n```\n\n凭证优先级 / Credential priority：OAuth access 未过期直用 → 过期前 60s 加独占锁自动刷新 →\n回落静态 key。（Valid OAuth access token is used directly; within 60s of expiry it is\nrefreshed under an exclusive lock file; otherwise falls back to the static key.）\n\n刷新锁为 `~/.cache/cr-report-token.lock`（wx 独占创建 + 自旋重试，最多等 5s）：\n并发 hook 同时刷新会导致旧 refresh_token 重放被服务端按重放处理并全链吊销。\n(The refresh lock serializes concurrent refreshes — replaying an old refresh token\nrevokes the whole grant chain server-side.)\n\n## 各客户端接入 / Per-client wiring\n\n### Claude Code（`~/.claude/settings.json`）\n\n```json\n{\n  \"hooks\": {\n    \"SessionStart\": [{\"hooks\": [{\"type\": \"command\",\n      \"command\": \"crewrouter-helper hook --harness claude_code\"}]}],\n    \"SessionEnd\":   [{\"hooks\": [{\"type\": \"command\",\n      \"command\": \"crewrouter-helper hook --harness claude_code\"}]}],\n    \"PostToolUse\":  [{\"hooks\": [{\"type\": \"command\",\n      \"command\": \"crewrouter-helper hook --harness claude_code\"}]}]\n  }\n}\n```\n\n事件类型从 stdin 的 `hook_event_name` 自动推断，三段命令完全相同。\n(Event type is inferred from `hook_event_name`; all three entries are identical.)\n\nQwen Code 同理：`~/.qwen/settings.json` 里把 `--harness` 改为 `qwen_code`\n（hooks 格式与 Claude 一致）。(Same for Qwen Code with harness id `qwen_code`.)\n\n### Codex（`~/.codex/config.toml`，v0.124+ 需 `codex_hooks = true`）\n\n```toml\n[hooks.PostToolUse]\ncommand = \"crewrouter-helper hook --harness codex\"\n```\n\n### Grok（无 hook → watch 模式常驻 / no hooks → resident watcher）\n\n```bash\nnohup crewrouter-helper watch --harness grok >/dev/null 2>&1 &\n```\n\ntail `~/.grok/sessions/**/updates.jsonl`：新会话目录 → `session_start`，\n`tool_call` 行 → `tool_use`；增量偏移存\n`~/.cache/cr-report-grok-state.json`，含半行保护。\n(New session directories produce session_start; tool_call lines produce tool_use.\nByte offsets persist in the state file with partial-line protection.)\n\n### Hermes / OpenClaw / DeepSeek Harness\n\n会话启动处直接调用 / Call at session start:\n\n```bash\ncrewrouter-helper emit --harness hermes --event session_start --session \"$SESSION_ID\"\n```\n\n### apiKeyHelper 场景 / For API-key helpers\n\nClaude Code 的 `apiKeyHelper` 可指向 `crewrouter-helper --print`\n（stdout 只输出 token，错误走 stderr 且退出非零）。\n(Point Claude Code's apiKeyHelper at `--print`: stdout carries only the token;\nerrors go to stderr with a non-zero exit.)\n\n## 环境变量 / Environment variables\n\n| 变量 / Variable | 作用 / Purpose |\n| --- | --- |\n| `CREWROUTER_URL` | 覆盖服务端地址（login 缺省也用它）/ Override server base URL |\n| `CREWROUTER_KEY` | 提供静态 Key 回落 / Static-key fallback credential |\n| `CREWROUTER_CONFIG` | 覆盖配置文件路径 / Config file path override |\n| `CR_REPORT_CONFIG` | 同上（兼容 Python 版）/ Same, Python-compatible alias |\n| `CREWROUTER_NO_BROWSER=1` | 不拉起浏览器，只打印授权链接 / Print auth URL only |\n| `CR_REPORT_NO_BROWSER=1` | 同上（兼容 Python 版）/ Same, Python-compatible alias |\n\n## 设计约定 / Design notes\n\n- **静默失败 / Silent failure**：hook 模式任何错误（配置缺失、网络失败、JSON 解析失败）\n  都静默退出 0，绝不阻塞客户端工具执行。(In hook mode every failure exits 0 silently.)\n- 密钥只存 `~/.config/cr-report.json` 一处且权限 600，客户端配置文件里不含密钥。\n  (Credentials live in one 600-permission file; client configs hold no secrets.)\n- 与服务端的契约：`POST /api/client-events`、`POST /oauth/token`、`GET /oauth/authorize`。\n  (Server contract: the three endpoints above.)\n\n## License\n\nGNU General Public License v3.0 only (GPL-3.0-only)\n\n## Links\n\n[CrewRouter - Github](https://github.com/BloretCrew/CrewRouter) [CrewRouter](https://crewrouter.bloret.net/) [QQ Discuss](https://qm.qq.com/q/kEt8fb41wc)\n","readmeFilename":"README.md"}