@nocville/npc 0.0.0-stage → 0.2.1
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/README.md +268 -2
- package/dist/cjs/cli.js +584 -0
- package/dist/cjs/core/api-key.js +69 -0
- package/dist/cjs/core/base-npc.js +160 -0
- package/dist/cjs/core/config.js +108 -0
- package/dist/cjs/core/event-npc.js +14 -0
- package/dist/cjs/core/logger.js +39 -0
- package/dist/cjs/core/polling-npc.js +65 -0
- package/dist/cjs/core/screen.js +28 -0
- package/dist/cjs/core/session-filter.js +150 -0
- package/dist/cjs/core/text.js +15 -0
- package/dist/cjs/core/thresholds.js +48 -0
- package/dist/cjs/core/types.js +10 -0
- package/dist/cjs/core/user-config.js +92 -0
- package/dist/cjs/doctor.js +130 -0
- package/dist/cjs/index.js +95 -0
- package/dist/cjs/npcs/agent-common/activity.js +291 -0
- package/dist/cjs/npcs/agent-common/git-stats.js +71 -0
- package/dist/cjs/npcs/agent-common/hook-runner.js +252 -0
- package/dist/cjs/npcs/agent-common/hook-settings.js +279 -0
- package/dist/cjs/npcs/agent-common/liveness.js +112 -0
- package/dist/cjs/npcs/agent-common/lock.js +99 -0
- package/dist/cjs/npcs/agent-common/runtime.js +154 -0
- package/dist/cjs/npcs/agent-common/session.js +412 -0
- package/dist/cjs/npcs/agent-common/shim.js +96 -0
- package/dist/cjs/npcs/agent-common/watchdog.js +149 -0
- package/dist/cjs/npcs/claude-code/defaults.js +20 -0
- package/dist/cjs/npcs/claude-code/hook-handler.js +139 -0
- package/dist/cjs/npcs/claude-code/index.js +104 -0
- package/dist/cjs/npcs/claude-code/setup.js +133 -0
- package/dist/cjs/npcs/claude-code/state-machine.js +130 -0
- package/dist/cjs/npcs/codex/defaults.js +32 -0
- package/dist/cjs/npcs/codex/hook-handler.js +116 -0
- package/dist/cjs/npcs/codex/index.js +92 -0
- package/dist/cjs/npcs/codex/rollout.js +246 -0
- package/dist/cjs/npcs/codex/setup.js +104 -0
- package/dist/cjs/npcs/codex/watcher.js +361 -0
- package/dist/cjs/npcs/cursor/defaults.js +15 -0
- package/dist/cjs/npcs/cursor/hook-handler.js +65 -0
- package/dist/cjs/npcs/cursor/index.js +72 -0
- package/dist/cjs/npcs/cursor/normalize.js +54 -0
- package/dist/cjs/npcs/cursor/setup.js +98 -0
- package/dist/cjs/npcs/gemini/defaults.js +15 -0
- package/dist/cjs/npcs/gemini/hook-handler.js +93 -0
- package/dist/cjs/npcs/gemini/index.js +69 -0
- package/dist/cjs/npcs/gemini/setup.js +98 -0
- package/dist/cjs/npcs/github-watcher/defaults.js +11 -0
- package/dist/cjs/npcs/github-watcher/format.js +21 -0
- package/dist/cjs/npcs/github-watcher/github-api.js +126 -0
- package/dist/cjs/npcs/github-watcher/index.js +148 -0
- package/dist/cjs/npcs/internet-connectivity/checks.js +92 -0
- package/dist/cjs/npcs/internet-connectivity/defaults.js +22 -0
- package/dist/cjs/npcs/internet-connectivity/index.js +251 -0
- package/dist/cjs/npcs/log-watcher/buffer.js +40 -0
- package/dist/cjs/npcs/log-watcher/defaults.js +12 -0
- package/dist/cjs/npcs/log-watcher/index.js +161 -0
- package/dist/cjs/npcs/log-watcher/tail.js +81 -0
- package/dist/cjs/npcs/process-watcher/defaults.js +9 -0
- package/dist/cjs/npcs/process-watcher/index.js +140 -0
- package/dist/cjs/npcs/process-watcher/process-scanner.js +114 -0
- package/dist/cjs/npcs/receptionist/defaults.js +9 -0
- package/dist/cjs/npcs/receptionist/index.js +120 -0
- package/dist/cjs/npcs/receptionist/weather.js +129 -0
- package/dist/cjs/npcs/system-monitor/collectors.js +68 -0
- package/dist/cjs/npcs/system-monitor/defaults.js +13 -0
- package/dist/cjs/npcs/system-monitor/index.js +105 -0
- package/dist/cjs/npcs/web-page-watcher/basic-mode.js +58 -0
- package/dist/cjs/npcs/web-page-watcher/capture.js +80 -0
- package/dist/cjs/npcs/web-page-watcher/defaults.js +31 -0
- package/dist/cjs/npcs/web-page-watcher/index.js +234 -0
- package/dist/cjs/npcs/web-page-watcher/pixelate.js +181 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +549 -0
- package/dist/core/api-key.d.ts +34 -0
- package/dist/core/api-key.js +64 -0
- package/dist/core/base-npc.d.ts +41 -0
- package/dist/core/base-npc.js +156 -0
- package/dist/core/config.d.ts +22 -0
- package/dist/core/config.js +101 -0
- package/dist/core/event-npc.d.ts +8 -0
- package/dist/core/event-npc.js +10 -0
- package/dist/core/logger.d.ts +11 -0
- package/dist/core/logger.js +35 -0
- package/dist/core/polling-npc.d.ts +18 -0
- package/dist/core/polling-npc.js +61 -0
- package/dist/core/screen.d.ts +11 -0
- package/dist/core/screen.js +24 -0
- package/dist/core/session-filter.d.ts +59 -0
- package/dist/core/session-filter.js +143 -0
- package/dist/core/text.d.ts +6 -0
- package/dist/core/text.js +12 -0
- package/dist/core/thresholds.d.ts +10 -0
- package/dist/core/thresholds.js +44 -0
- package/dist/core/types.d.ts +60 -0
- package/dist/core/types.js +7 -0
- package/dist/core/user-config.d.ts +43 -0
- package/dist/core/user-config.js +85 -0
- package/dist/doctor.d.ts +8 -0
- package/dist/doctor.js +126 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +26 -0
- package/dist/npcs/agent-common/activity.d.ts +42 -0
- package/dist/npcs/agent-common/activity.js +280 -0
- package/dist/npcs/agent-common/git-stats.d.ts +11 -0
- package/dist/npcs/agent-common/git-stats.js +67 -0
- package/dist/npcs/agent-common/hook-runner.d.ts +62 -0
- package/dist/npcs/agent-common/hook-runner.js +245 -0
- package/dist/npcs/agent-common/hook-settings.d.ts +75 -0
- package/dist/npcs/agent-common/hook-settings.js +265 -0
- package/dist/npcs/agent-common/liveness.d.ts +12 -0
- package/dist/npcs/agent-common/liveness.js +105 -0
- package/dist/npcs/agent-common/lock.d.ts +6 -0
- package/dist/npcs/agent-common/lock.js +95 -0
- package/dist/npcs/agent-common/runtime.d.ts +16 -0
- package/dist/npcs/agent-common/runtime.js +149 -0
- package/dist/npcs/agent-common/session.d.ts +192 -0
- package/dist/npcs/agent-common/session.js +390 -0
- package/dist/npcs/agent-common/shim.d.ts +4 -0
- package/dist/npcs/agent-common/shim.js +90 -0
- package/dist/npcs/agent-common/watchdog.d.ts +16 -0
- package/dist/npcs/agent-common/watchdog.js +144 -0
- package/dist/npcs/claude-code/defaults.d.ts +15 -0
- package/dist/npcs/claude-code/defaults.js +17 -0
- package/dist/npcs/claude-code/hook-handler.d.ts +40 -0
- package/dist/npcs/claude-code/hook-handler.js +131 -0
- package/dist/npcs/claude-code/index.d.ts +36 -0
- package/dist/npcs/claude-code/index.js +92 -0
- package/dist/npcs/claude-code/setup.d.ts +58 -0
- package/dist/npcs/claude-code/setup.js +121 -0
- package/dist/npcs/claude-code/state-machine.d.ts +28 -0
- package/dist/npcs/claude-code/state-machine.js +125 -0
- package/dist/npcs/codex/defaults.d.ts +24 -0
- package/dist/npcs/codex/defaults.js +28 -0
- package/dist/npcs/codex/hook-handler.d.ts +24 -0
- package/dist/npcs/codex/hook-handler.js +110 -0
- package/dist/npcs/codex/index.d.ts +21 -0
- package/dist/npcs/codex/index.js +76 -0
- package/dist/npcs/codex/rollout.d.ts +39 -0
- package/dist/npcs/codex/rollout.js +242 -0
- package/dist/npcs/codex/setup.d.ts +37 -0
- package/dist/npcs/codex/setup.js +96 -0
- package/dist/npcs/codex/watcher.d.ts +65 -0
- package/dist/npcs/codex/watcher.js +356 -0
- package/dist/npcs/cursor/defaults.d.ts +9 -0
- package/dist/npcs/cursor/defaults.js +11 -0
- package/dist/npcs/cursor/hook-handler.d.ts +8 -0
- package/dist/npcs/cursor/hook-handler.js +60 -0
- package/dist/npcs/cursor/index.d.ts +18 -0
- package/dist/npcs/cursor/index.js +57 -0
- package/dist/npcs/cursor/normalize.d.ts +6 -0
- package/dist/npcs/cursor/normalize.js +49 -0
- package/dist/npcs/cursor/setup.d.ts +29 -0
- package/dist/npcs/cursor/setup.js +90 -0
- package/dist/npcs/gemini/defaults.d.ts +9 -0
- package/dist/npcs/gemini/defaults.js +11 -0
- package/dist/npcs/gemini/hook-handler.d.ts +10 -0
- package/dist/npcs/gemini/hook-handler.js +87 -0
- package/dist/npcs/gemini/index.d.ts +17 -0
- package/dist/npcs/gemini/index.js +56 -0
- package/dist/npcs/gemini/setup.d.ts +29 -0
- package/dist/npcs/gemini/setup.js +90 -0
- package/dist/npcs/github-watcher/defaults.d.ts +8 -0
- package/dist/npcs/github-watcher/defaults.js +8 -0
- package/dist/npcs/github-watcher/format.d.ts +3 -0
- package/dist/npcs/github-watcher/format.js +18 -0
- package/dist/npcs/github-watcher/github-api.d.ts +55 -0
- package/dist/npcs/github-watcher/github-api.js +120 -0
- package/dist/npcs/github-watcher/index.d.ts +35 -0
- package/dist/npcs/github-watcher/index.js +144 -0
- package/dist/npcs/internet-connectivity/checks.d.ts +24 -0
- package/dist/npcs/internet-connectivity/checks.js +84 -0
- package/dist/npcs/internet-connectivity/defaults.d.ts +20 -0
- package/dist/npcs/internet-connectivity/defaults.js +19 -0
- package/dist/npcs/internet-connectivity/index.d.ts +55 -0
- package/dist/npcs/internet-connectivity/index.js +246 -0
- package/dist/npcs/log-watcher/buffer.d.ts +18 -0
- package/dist/npcs/log-watcher/buffer.js +34 -0
- package/dist/npcs/log-watcher/defaults.d.ts +9 -0
- package/dist/npcs/log-watcher/defaults.js +9 -0
- package/dist/npcs/log-watcher/index.d.ts +45 -0
- package/dist/npcs/log-watcher/index.js +157 -0
- package/dist/npcs/log-watcher/tail.d.ts +9 -0
- package/dist/npcs/log-watcher/tail.js +78 -0
- package/dist/npcs/process-watcher/defaults.d.ts +6 -0
- package/dist/npcs/process-watcher/defaults.js +6 -0
- package/dist/npcs/process-watcher/index.d.ts +26 -0
- package/dist/npcs/process-watcher/index.js +136 -0
- package/dist/npcs/process-watcher/process-scanner.d.ts +19 -0
- package/dist/npcs/process-watcher/process-scanner.js +110 -0
- package/dist/npcs/receptionist/defaults.d.ts +6 -0
- package/dist/npcs/receptionist/defaults.js +6 -0
- package/dist/npcs/receptionist/index.d.ts +29 -0
- package/dist/npcs/receptionist/index.js +116 -0
- package/dist/npcs/receptionist/weather.d.ts +37 -0
- package/dist/npcs/receptionist/weather.js +121 -0
- package/dist/npcs/system-monitor/collectors.d.ts +45 -0
- package/dist/npcs/system-monitor/collectors.js +60 -0
- package/dist/npcs/system-monitor/defaults.d.ts +7 -0
- package/dist/npcs/system-monitor/defaults.js +10 -0
- package/dist/npcs/system-monitor/index.d.ts +27 -0
- package/dist/npcs/system-monitor/index.js +101 -0
- package/dist/npcs/web-page-watcher/basic-mode.d.ts +16 -0
- package/dist/npcs/web-page-watcher/basic-mode.js +52 -0
- package/dist/npcs/web-page-watcher/capture.d.ts +49 -0
- package/dist/npcs/web-page-watcher/capture.js +75 -0
- package/dist/npcs/web-page-watcher/defaults.d.ts +19 -0
- package/dist/npcs/web-page-watcher/defaults.js +27 -0
- package/dist/npcs/web-page-watcher/index.d.ts +42 -0
- package/dist/npcs/web-page-watcher/index.js +230 -0
- package/dist/npcs/web-page-watcher/pixelate.d.ts +36 -0
- package/dist/npcs/web-page-watcher/pixelate.js +172 -0
- package/package.json +73 -3
package/README.md
CHANGED
|
@@ -1,3 +1,269 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @nocville/npc
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Put your AI coding sessions and your infrastructure in the [Nocville](https://nocville.com)
|
|
4
|
+
office as live NPCs. Each Claude Code, Codex, Gemini CLI or Cursor session becomes a coworker named after its
|
|
5
|
+
project (`Claude · nocville`, `Codex · gridbreak`) who walks to a desk while working, raises
|
|
6
|
+
a hand when it needs you, dozes when idle, and shows what it's doing on its speech bubble and
|
|
7
|
+
desk sign: `Editing src/GameScene.ts`, `Running pnpm test`, `Searching for 'reconnect'`,
|
|
8
|
+
`Needs your approval`, `Thinking…`. It leaves the office when the session ends.
|
|
9
|
+
|
|
10
|
+
Requires Node.js 20+. Your team API key is in your Nocville team settings.
|
|
11
|
+
|
|
12
|
+
## Quick start: AI coworkers
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @nocville/npc setup
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Paste your key at the prompt (input is hidden, so the key never lands in your shell history).
|
|
19
|
+
For scripts, pass `--api-key=<your team key>` or set `NOCVILLE_API_KEY` instead. That's it. The command saves your key to `~/.config/nocville/config.json` (mode 0600), then
|
|
20
|
+
hooks up whichever agents you have installed:
|
|
21
|
+
|
|
22
|
+
- **Claude Code**: adds hooks to `~/.claude/settings.json`. New sessions show up right away;
|
|
23
|
+
restart sessions that are already running.
|
|
24
|
+
- **Codex**: adds hooks to `~/.codex/hooks.json`. Codex won't run a new hook until you've
|
|
25
|
+
approved it, so start Codex once and run **`/hooks`** to trust the Nocville hooks.
|
|
26
|
+
|
|
27
|
+
- **Gemini CLI**: adds eight telemetry hooks to `~/.gemini/settings.json`, preserving your
|
|
28
|
+
settings and existing hooks. Start a new session after setup. Hooks return only `{}`.
|
|
29
|
+
|
|
30
|
+
- **Cursor**: adds native hooks to `~/.cursor/hooks.json`. Existing Nocville Claude hooks
|
|
31
|
+
also detect Cursor when its third-party hook imports are enabled. Both installations share
|
|
32
|
+
one coworker and deduplicate matching events. No permission decisions or model output are sent.
|
|
33
|
+
|
|
34
|
+
Self-hosting or developing locally? Add `--api-url=http://localhost:3601`. To send sessions to
|
|
35
|
+
a map other than your team's default, add `--map="Trading Floor"`.
|
|
36
|
+
|
|
37
|
+
Prefer a global install? Run `npm i -g @nocville/npc`, then `nocville-npc setup --api-key=…`.
|
|
38
|
+
When setup runs through `npx`, it copies itself to `~/.config/nocville/runtime/` so the hooks
|
|
39
|
+
keep working after npm clears its cache.
|
|
40
|
+
|
|
41
|
+
### Choose which sessions appear
|
|
42
|
+
|
|
43
|
+
By default every agent session publishes to your office. To keep some out, or to show only
|
|
44
|
+
some, edit `~/.config/nocville/sessions.json` (setup creates an empty one):
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"allow": { "projects": [], "sessions": [] },
|
|
49
|
+
"deny": { "projects": ["client-*", "~/work/secret"], "sessions": ["*private*"] }
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- **Empty lists** (or no file): every session publishes.
|
|
54
|
+
- **`deny` always wins.** If any `allow` entry is set, **only** matching sessions publish.
|
|
55
|
+
- **`projects`**: a folder name anywhere in the session's working directory (`client-*` also
|
|
56
|
+
covers `~/work/client-acme/api`), or a path containing `/` (`~/work/secret` covers that folder
|
|
57
|
+
and everything inside it).
|
|
58
|
+
- **`sessions`**: a Claude Code session name (set with `/rename`). Unnamed sessions never match.
|
|
59
|
+
- Patterns are case-insensitive; `*` matches anything, `?` one character.
|
|
60
|
+
|
|
61
|
+
The file is read on every update, so edits apply to running sessions without reinstalling: a
|
|
62
|
+
session that becomes filtered out leaves the office on its next update. If the file can't be
|
|
63
|
+
parsed, nothing publishes until it's fixed. `npx @nocville/npc sessions` shows the rules and
|
|
64
|
+
checks the current folder (`--project=<dir>`, `--name=<session name>` to test others).
|
|
65
|
+
|
|
66
|
+
### Per-agent commands
|
|
67
|
+
|
|
68
|
+
| Claude Code | Codex |
|
|
69
|
+
| ------------------------------------ | ---------------------------------------------- |
|
|
70
|
+
| `nocville-npc claude-code setup` | `nocville-npc codex setup` (then `/hooks`) |
|
|
71
|
+
| `nocville-npc claude-code uninstall` | `nocville-npc codex uninstall` |
|
|
72
|
+
| | `nocville-npc codex watch` (no-hooks fallback) |
|
|
73
|
+
|
|
74
|
+
`nocville-npc gemini setup` and `nocville-npc gemini uninstall` manage Gemini alone.
|
|
75
|
+
Gemini uses a 5000 ms hook timeout; pushes and end-of-turn git summaries are detached.
|
|
76
|
+
Its Node process is identified by the Gemini executable path, not an unrelated Node parent.
|
|
77
|
+
|
|
78
|
+
`nocville-npc cursor setup` and `nocville-npc cursor uninstall` manage native Cursor hooks.
|
|
79
|
+
Native commands use 10-second timeouts. Setup installs only sessionStart/sessionEnd,
|
|
80
|
+
beforeSubmitPrompt, postToolUse/postToolUseFailure, afterFileEdit, stop, subagentStop and
|
|
81
|
+
preCompact; it removes older Nocville permission hooks while preserving other hooks.
|
|
82
|
+
Activity comes from completed tools. Native and imported Cursor invocations return exactly
|
|
83
|
+
`{}` with no decision fields. Payload fields identify imported Cursor; `CURSOR_VERSION`
|
|
84
|
+
alone never reclassifies Claude launched inside its terminal. The launcher suppresses child
|
|
85
|
+
stdout for every agent, including debug logs, and emits only the appropriate neutral response.
|
|
86
|
+
Cursor does not watch the editor process or start a watchdog: an abandoned conversation uses
|
|
87
|
+
the one-hour fallback heartbeat interval (unknown after two hours, despawn ten minutes later).
|
|
88
|
+
Uninstall intentionally leaves `{"version":1}` when no other settings remain.
|
|
89
|
+
|
|
90
|
+
Cursor's [documented tool names](https://cursor.com/docs/hooks#configuration) include Grep,
|
|
91
|
+
Delete, Task and MCP tools. Their summaries use the shared redaction/path handling; MCP names
|
|
92
|
+
are normalized to the shared MCP format. Real Cursor Shell/Read/Write verification with both
|
|
93
|
+
Claude-imported-only and native hooks is still required before a public support claim.
|
|
94
|
+
|
|
95
|
+
`nocville-npc uninstall` removes every Nocville hook. `nocville-npc init` only saves
|
|
96
|
+
credentials. Every setup command takes the key from `--api-key`, then `NOCVILLE_API_KEY`, then
|
|
97
|
+
the saved config, and otherwise prompts for it (in a terminal) or exits with an error. `nocville-npc doctor` checks connectivity and sends a test push.
|
|
98
|
+
|
|
99
|
+
### What you'll see
|
|
100
|
+
|
|
101
|
+
| Agent state | NPC | Desk sign / bubble |
|
|
102
|
+
| -------------------------------- | ------------------------------------- | ---------------------------------------------- |
|
|
103
|
+
| Prompt submitted | walks to a desk, sits | `Thinking…` |
|
|
104
|
+
| Using a tool | stays at the desk | `Editing apps/web/x.ts`, `Running pnpm test` … |
|
|
105
|
+
| Permission prompt / question | stands up and raises a hand | `Needs your approval: Running rm -rf dist` |
|
|
106
|
+
| Turn finished, or at the prompt | dozes at the desk | `Done — waiting for next task` |
|
|
107
|
+
| Session ends (exit, `/clear`, …) | leaves the office (immediate despawn) | |
|
|
108
|
+
|
|
109
|
+
**Privacy:** prompts, file contents, edit text, and command output are never sent. Commands
|
|
110
|
+
are shortened to their first line, and anything that looks like a secret is redacted first:
|
|
111
|
+
env assignments, `--token=`/`--password` flags, bearer headers, URL credentials, and long
|
|
112
|
+
key-like strings. Paths are shown relative to the project.
|
|
113
|
+
|
|
114
|
+
**Lifecycle and overhead:** normal hooks run asynchronously, update a locked local state file,
|
|
115
|
+
and hand HTTP delivery to a detached process. Same-phase bursts coalesce at 1.5 seconds.
|
|
116
|
+
SessionEnd stays synchronous with a short timeout to deliver the offline update; failures
|
|
117
|
+
remain pending for retry. Hooks never output instructions or permission decisions.
|
|
118
|
+
|
|
119
|
+
A watchdog checks a known agent process every 15 seconds and heartbeats once a minute.
|
|
120
|
+
A killed process leaves the office on the next check. If the machine sleeps or loses power,
|
|
121
|
+
the NPC becomes unknown after three minutes and disappears after thirteen. Hosts where
|
|
122
|
+
process liveness cannot be established retain the legacy one-hour heartbeat fallback.
|
|
123
|
+
Claude subagent activity appears below the parent's current activity and disappears when
|
|
124
|
+
the subagent stops (or after ten minutes without activity).
|
|
125
|
+
|
|
126
|
+
Setup installs a stable `~/.config/nocville/bin/nocville-hook` launcher (respecting
|
|
127
|
+
`XDG_CONFIG_HOME` and `NOCVILLE_CONFIG`) and an immutable runtime copy when needed.
|
|
128
|
+
Re-running setup updates the runtime pointer without changing the hook command or Codex's
|
|
129
|
+
command trust. Old snapshots remain available to running watchdogs. Windows uses the sibling
|
|
130
|
+
`nocville-hook.cmd` launcher, which resolves the saved Node path and runs the same bootstrap.
|
|
131
|
+
Windows setup writes plain commands, never `-EncodedCommand` or an execution-policy override.
|
|
132
|
+
Re-running setup replaces the former encoded commands; uninstall still recognizes them.
|
|
133
|
+
|
|
134
|
+
| Agent | Windows command host and verification |
|
|
135
|
+
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
136
|
+
| Claude Code | Explicit per-hook `shell: "powershell"`; invokes `& '<shim>.cmd' claude-code hook`. Claude selects PowerShell 7 or falls back to 5.1. CI exercises both. [Claude hook shell reference](https://code.claude.com/docs/en/hooks#windows-powershell-tool). |
|
|
137
|
+
| Gemini | Its hook runner selects PowerShell 7 or 5.1. The saved `cmd.exe /d /s /c --% ...` preserves cmd quoting, with a terminating newline before Gemini's appended exit check. CI exercises both hosts with that check. [Hook reference](https://geminicli.com/docs/hooks/reference/), [runner](https://github.com/google-gemini/gemini-cli/blob/main/packages/core/src/hooks/hookRunner.ts), [shell selection](https://github.com/google-gemini/gemini-cli/blob/main/packages/core/src/utils/shell-utils.ts). |
|
|
138
|
+
| Cursor | Explicit `cmd.exe /d /s /c` launcher; CI executes the saved string under cmd. The [published hook contract](https://cursor.com/docs/hooks) does not specify the Windows outer shell; real Windows Cursor verification remains required. |
|
|
139
|
+
| Codex | Explicit `cmd.exe /d /s /c` launcher; CI executes the saved string under cmd. The [published hook contract](https://learn.chatgpt.com/docs/hooks) does not identify the Windows outer shell; real Windows Codex verification remains required. |
|
|
140
|
+
|
|
141
|
+
PowerShell's [stop-parsing token](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing#the-stop-parsing-token)
|
|
142
|
+
ends at a newline, not a semicolon. Keep Gemini's saved newline: its runner appends PowerShell
|
|
143
|
+
code to the command. No event input is interpolated into shell commands. Windows support remains
|
|
144
|
+
unverified until the Windows CI job and real-agent checks pass; macOS tests cannot establish it.
|
|
145
|
+
**Windows Cursor users:** install native hooks with `nocville-npc cursor setup`; do not rely on
|
|
146
|
+
Cursor importing Claude Code hooks. Claude's saved hook uses PowerShell syntax and an explicit
|
|
147
|
+
`shell` field. If Cursor's import path ignores that field and uses cmd, the imported command can
|
|
148
|
+
fail before the shim runs and produce hook errors. Nocville cannot control Cursor's import path.
|
|
149
|
+
|
|
150
|
+
Windows real-agent owner checklist (required before support claims):
|
|
151
|
+
|
|
152
|
+
- Run the native Windows CI job, including PowerShell 5.1/7 and a spaced `O’Neil` profile path.
|
|
153
|
+
- Verify native Cursor Shell/Read/Write events after `nocville-npc cursor setup`.
|
|
154
|
+
- With Claude hooks also installed, check whether Cursor imports them and honors their `shell`
|
|
155
|
+
field. Record agent versions and any duplicate/error events; verify native Cursor hooks work
|
|
156
|
+
independently. Do not count an imported Claude hook as proof of native Cursor support.
|
|
157
|
+
- Verify the actual Claude, Gemini and Codex hosts using their installed saved commands.
|
|
158
|
+
|
|
159
|
+
Claude's single-quoted path doubles straight and curly apostrophes according to
|
|
160
|
+
[PowerShell quoting rules](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules#including-quote-characters-in-a-string).
|
|
161
|
+
|
|
162
|
+
Both launchers discard child stdout and preserve stderr; all SDK logger levels use stderr.
|
|
163
|
+
If Node is unavailable, the shim drains stdin and returns neutral `{}` for Cursor/Gemini
|
|
164
|
+
and Claude hooks (which may have been imported by Cursor); Codex stays silent. Session records are local, including terminal
|
|
165
|
+
records that prevent late events from reviving an ended NPC; `cleanup` removes old records.
|
|
166
|
+
|
|
167
|
+
### How the Codex integration works
|
|
168
|
+
|
|
169
|
+
Codex supports Claude-style lifecycle hooks (`SessionStart`, `UserPromptSubmit`,
|
|
170
|
+
`PreToolUse`, `PermissionRequest`, `Stop`, `SessionEnd`, …) configured in
|
|
171
|
+
`~/.codex/hooks.json`. Setup merges a Nocville entry into each event, keeps your existing
|
|
172
|
+
hooks, makes a one-time `hooks.json.nocville-backup`, and is safe to run again.
|
|
173
|
+
|
|
174
|
+
`nocville-npc codex watch` is a deprecated, best-effort fallback for builds without hooks. It
|
|
175
|
+
reads the rollout logs Codex writes to `~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl`. It
|
|
176
|
+
shows one NPC per interactive session (subagent and reviewer threads are skipped; add
|
|
177
|
+
`--include-exec` to include `codex exec` runs). A session leaves the office after 30 minutes
|
|
178
|
+
without log activity (`--idle-timeout=<minutes>`) or when you press Ctrl-C. If hooks are
|
|
179
|
+
installed for a session (any hook state file, including an old terminal record), the watcher
|
|
180
|
+
leaves that session to them. `doctor` warns when both modes are running.
|
|
181
|
+
|
|
182
|
+
## Monitoring NPCs
|
|
183
|
+
|
|
184
|
+
Long-running processes that each collect from one source and push status. Their NPC spawns
|
|
185
|
+
on your map automatically and despawns when you press Ctrl-C. Once you've run
|
|
186
|
+
`nocville-npc init`, no `--api-key` is needed.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Common options:
|
|
190
|
+
# --api-key=<key> Team API key (or NOCVILLE_API_KEY, or saved via `init`)
|
|
191
|
+
# --api-url=<url> Default https://nocville.com (or NOCVILLE_API_URL)
|
|
192
|
+
# --service-id=<id> Service ID (or NOCVILLE_SERVICE_ID)
|
|
193
|
+
# --name=<banner name> Friendly NPC name (or NOCVILLE_NAME)
|
|
194
|
+
# --map=<id-or-name> Target map (or NOCVILLE_MAP). Default: the team's default map
|
|
195
|
+
# --debug Verbose logging
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
| NPC | What it does | Example |
|
|
199
|
+
| ----------------------- | -------------------------------------------------- | ------------------------------------------------------ |
|
|
200
|
+
| `system-monitor` | CPU / memory / disk / load with sparklines | `nocville-npc system-monitor --cpu-warn=75` |
|
|
201
|
+
| `internet-connectivity` | DNS, HTTP and TCP latency checks | `nocville-npc internet-connectivity` |
|
|
202
|
+
| `process-watcher` | Watches named processes, calls out deaths | `nocville-npc process-watcher --processes=nginx,redis` |
|
|
203
|
+
| `log-watcher` | Error bursts in log files, last lines on a monitor | `nocville-npc log-watcher --files=/var/log/app.log` |
|
|
204
|
+
| `receptionist` | Time and weather at the entrance, greets players | `nocville-npc receptionist --location="Berlin"` |
|
|
205
|
+
| `github-watcher` | New commits on a commit board | `nocville-npc github-watcher --repo=owner/name` |
|
|
206
|
+
| `web-page-watcher` | A web page rendered as a pixel-art TV | `nocville-npc web-page-watcher --url=https://…` |
|
|
207
|
+
|
|
208
|
+
Run `nocville-npc --help` to see every flag. A few notes:
|
|
209
|
+
|
|
210
|
+
- **log-watcher**: `--error-pattern="ERROR|FATAL" --window=300 --error-warn=5 --error-crit=20`.
|
|
211
|
+
- **receptionist**: weather comes from the keyless open-meteo API. Set the place with
|
|
212
|
+
`--lat=52.5 --lon=13.4` or `--location=…` (otherwise it uses IP geolocation). Add
|
|
213
|
+
`--fahrenheit` for °F.
|
|
214
|
+
- **github-watcher**: uses ETag polling. Pass `--token=$GITHUB_TOKEN` for a higher rate limit.
|
|
215
|
+
- **web-page-watcher**: the pixel-art TV needs `npm i puppeteer-core` and a local
|
|
216
|
+
Chrome/Chromium (`--chrome-path` or `CHROME_PATH`). Without them it falls back to a
|
|
217
|
+
title/status ticker. Other options: `--mode=auto|screenshot|basic` and `--screen=160x120`.
|
|
218
|
+
|
|
219
|
+
## Programmatic use
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { SystemMonitorNPC, PollingNPC } from '@nocville/npc';
|
|
223
|
+
import type { CollectedMetrics } from '@nocville/npc';
|
|
224
|
+
|
|
225
|
+
await new SystemMonitorNPC({
|
|
226
|
+
apiUrl: 'https://nocville.com',
|
|
227
|
+
apiKey: 'noc_…',
|
|
228
|
+
serviceId: 'web-1',
|
|
229
|
+
}).start();
|
|
230
|
+
|
|
231
|
+
class MyNPC extends PollingNPC {
|
|
232
|
+
get name() {
|
|
233
|
+
return 'my-npc';
|
|
234
|
+
}
|
|
235
|
+
async collect(): Promise<CollectedMetrics> {
|
|
236
|
+
return { status: 'healthy', mood: 'happy', message: 'All good', metrics: { qps: 42 } };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Developing in the monorepo
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
pnpm install
|
|
245
|
+
pnpm --filter @nocville/npc build
|
|
246
|
+
pnpm --filter @nocville/npc test
|
|
247
|
+
node libs/nocville-npc-library/dist/cli.js --help
|
|
248
|
+
SMOKE_STUB=1 pnpm --filter @nocville/npc smoke # every payload shape, no server needed
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Watch an AI-coworker NPC without running an agent.** `simulate` plays a scripted session
|
|
252
|
+
(start → prompt → Read → Edit → `pnpm test` → approval wait → idle → end) through the real
|
|
253
|
+
built hook handlers. It works in a throwaway HOME, so your `~/.claude` and `~/.codex` are
|
|
254
|
+
untouched, and the NPC appears as "Claude · demo" (or "Codex · demo"):
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
pnpm --filter @nocville/npc simulate claude --api-key=<key> --api-url=http://localhost:3601
|
|
258
|
+
pnpm --filter @nocville/npc simulate codex --api-key=<key> --project=gridbreak --fast
|
|
259
|
+
# --hold stay idle after Stop until Ctrl-C, then end the session
|
|
260
|
+
# --fast 5x shorter pauses (CI)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Real hooks against your local checkout.** This writes real hooks into `~/.claude` and
|
|
264
|
+
`~/.codex` that run your working copy's `dist/cli.js`:
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
node libs/nocville-npc-library/dist/cli.js setup --api-key=<key> --api-url=http://localhost:3601
|
|
268
|
+
node libs/nocville-npc-library/dist/cli.js uninstall # remove them again
|
|
269
|
+
```
|