aisnitch 0.2.22 → 0.2.23

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 CHANGED
@@ -1,300 +1,253 @@
1
- # AISnitch
1
+ # 🤖 AISnitch
2
2
 
3
- **See what your AI agents are doing. All of them. In real time.**
3
+ > **See everything your AI coding tools are doing in one place, in real time.**
4
4
 
5
- [![CI](https://github.com/vava-nessa/AISnitch/actions/workflows/ci.yml/badge.svg)](https://github.com/vava-nessa/AISnitch/actions/workflows/ci.yml)
6
- [![npm](https://img.shields.io/npm/v/aisnitch?logo=npm&label=aisnitch)](https://www.npmjs.com/package/aisnitch)
7
- [![npm](https://img.shields.io/npm/v/@aisnitch/client?logo=npm&label=@aisnitch/client)](https://www.npmjs.com/package/@aisnitch/client)
8
- [![Node >=20](https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
9
- [![License: Apache-2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](./LICENSE)
10
-
11
- AISnitch is a local daemon that captures activity from **every AI coding tool** running on your machine — Claude Code, OpenCode, Gemini CLI, Codex, Goose, Aider, Copilot CLI, OpenClaw, and any CLI via PTY fallback — normalizes everything into a single event stream, and broadcasts it over WebSocket.
12
-
13
- - **One stream, all tools** — no more switching between terminals to see what each agent is doing
14
- - **Zero storage** — pure memory transit, nothing persists to disk, ever
15
- - **Build anything on top** — dashboards, sound engines, animated companions, Slack bots, menu bar widgets
5
+ ```
6
+ ┌─────────────────────────────────────────────────────────────────┐
7
+ │ │
8
+ │ Claude Code OpenCode Gemini CLI Aider Codex │
9
+ │ │ │ │ │ │ │
10
+ │ └──────────────┴───────────┴──────────┴─────────┘ │
11
+ │ │ │
12
+ │ ┌────────▼────────┐ │
13
+ │ │ AISnitch │ │
14
+ │ │ ┌─────────┐ │ │
15
+ │ │ │ TUI │ │ ← Dashboard (real-time)
16
+ │ │ └─────────┘ │ │
17
+ │ │ ┌─────────┐ │ │
18
+ │ │ │ Webhook │ │ ← Build anything │
19
+ │ │ └─────────┘ │ │
20
+ │ └─────────────────┘ │
21
+ │ │
22
+ └─────────────────────────────────────────────────────────────────┘
23
+ ```
16
24
 
17
- <!-- TODO: Add TUI demo GIF here -->
25
+ **One command. Every agent. Every project. Live.**
18
26
 
19
27
  ---
20
28
 
21
- ## Table of Contents
22
-
23
- - [Why AISnitch?](#why-aisnitch)
24
- - [Quick Start](#quick-start)
25
- - [Install](#install)
26
- - [Ecosystem](#ecosystem)
27
- - [How It Works](#how-it-works)
28
- - [Architecture](#architecture)
29
- - [Supported Tools](#supported-tools)
30
- - [Event Model](#event-model)
31
- - [Build on Top of AISnitch](#build-on-top-of-aisnitch)
32
- - [CLI Reference](#cli-reference)
33
- - [TUI Keybinds](#tui-keybinds)
34
- - [Config Reference](#config-reference)
35
- - [Development](#development)
36
- - [License](#license)
29
+ ## Why AISnitch?
37
30
 
38
- ---
31
+ You have **multiple AI coding assistants** running at the same time:
39
32
 
40
- ## Why AISnitch?
33
+ ```
34
+ 🔵 Claude Code → working on your main project
35
+ 🟡 OpenCode → reviewing a PR
36
+ 🟣 Codex → writing tests
37
+ 🟢 Aider → refactoring legacy code
38
+ ```
41
39
 
42
- You run Claude Code on your main project, Codex on the API, Aider reviewing a legacy repo. Three agents, three terminals, no shared visibility. You tab-switch constantly. You miss a permission prompt. You don't know which one is idle and which one is burning tokens.
40
+ **The problem?** You have 4 terminals open, tabbing between them, missing things, context-switching like crazy.
43
41
 
44
- **AISnitch solves this in one line:**
42
+ **The solution?**
45
43
 
46
44
  ```bash
47
45
  aisnitch start
48
46
  ```
49
47
 
50
- Now every tool's activity flows into one dashboard. You see who's thinking, who's coding, who needs input, and who's hit a rate limit — all at once, in real time.
48
+ Now you see **everything in one dashboard**:
51
49
 
52
- Want to build your own UI instead? The entire stream is available on `ws://127.0.0.1:4820` — connect with the [Client SDK](#ecosystem) and build dashboards, sound engines, animated companions, or anything else.
50
+ ```
51
+ ┌─────────────────────────────────────────────────────────────┐
52
+ │ 🤖 AISnitch [q] quit [?] help │
53
+ ├─────────────────────────────────────────────────────────────┤
54
+ │ 🔵 Claude Code ● thinking... │ 📝 src/app.ts │
55
+ │ 🟡 OpenCode ✓ idle │ 📁 /projects/api │
56
+ │ 🟣 Codex ⏳ coding... │ 📄 tests/users.test.ts │
57
+ │ 🟢 Aider ● task: "cleanup" │ 📁 /legacy/db │
58
+ ├─────────────────────────────────────────────────────────────┤
59
+ │ Events (42) [Space] freeze [c] clear │
60
+ │ ──────────────────────────────────────────────────────────── │
61
+ │ 🔵 14:30:01 agent.thinking "Implementing user auth..." │
62
+ │ 🔵 14:29:58 agent.coding Edit → src/auth/login.ts │
63
+ │ 🟡 14:29:55 agent.idle waiting for prompt... │
64
+ │ 🟣 14:29:52 tool_call Bash → git status │
65
+ └─────────────────────────────────────────────────────────────┘
66
+ ```
53
67
 
54
68
  ---
55
69
 
56
- ## Quick Start
70
+ ## 🚀 Quick Start (30 seconds)
71
+
72
+ ### 1. Install
57
73
 
58
74
  ```bash
59
- # Install and run
75
+ # npm (recommended)
60
76
  npm i -g aisnitch
61
- aisnitch start
62
77
 
63
- # Try it without any AI tool — simulated events
64
- aisnitch start --mock all
78
+ # or Homebrew
79
+ brew install aisnitch
65
80
  ```
66
81
 
67
- That's it. The TUI dashboard opens, and you see live activity from every configured AI tool.
68
-
69
- To set up tools:
82
+ ### 2. Run
70
83
 
71
84
  ```bash
72
- aisnitch setup claude-code # hooks into Claude Code
73
- aisnitch setup opencode # hooks into OpenCode
74
- aisnitch adapters # check what's enabled
85
+ aisnitch start
75
86
  ```
76
87
 
77
- ---
78
-
79
- ## Install
88
+ That's it! The dashboard opens with live events from all configured tools.
80
89
 
81
- **npm (recommended):**
90
+ **No AI tools yet?** Try the demo mode:
82
91
 
83
92
  ```bash
84
- npm i -g aisnitch
93
+ aisnitch start --mock all
85
94
  ```
86
95
 
87
- **Homebrew:**
96
+ ### 3. Connect your tools
88
97
 
89
98
  ```bash
90
- brew install aisnitch
91
- ```
92
-
93
- **From source:**
99
+ # Pick your tools
100
+ aisnitch setup claude-code # hooks into Claude Code
101
+ aisnitch setup opencode # hooks into OpenCode
102
+ aisnitch setup aider # hooks into Aider
94
103
 
95
- ```bash
96
- git clone https://github.com/vava-nessa/AISnitch.git
97
- cd AISnitch
98
- pnpm install && pnpm build
99
- node dist/cli/index.js start
104
+ # Verify everything
105
+ aisnitch adapters
100
106
  ```
101
107
 
102
108
  ---
103
109
 
104
- ## Ecosystem
110
+ ## 🎯 Common Use Cases
111
+
112
+ ### "I want to see all my AI agents in real time"
113
+
114
+ ```bash
115
+ aisnitch start
116
+ ```
105
117
 
106
- AISnitch ships as two packages with distinct audiences:
118
+ Opens the TUI dashboard. Live events stream in as your tools work.
107
119
 
108
- | Package | For | Install |
109
- |---|---|---|
110
- | [`aisnitch`](https://www.npmjs.com/package/aisnitch) | **Users** — the daemon, CLI, TUI dashboard, adapters | `npm i -g aisnitch` |
111
- | [`@aisnitch/client`](https://www.npmjs.com/package/@aisnitch/client) | **Developers** — TypeScript SDK to consume the event stream | `pnpm add @aisnitch/client zod` |
120
+ ### "I want to build something on top of AISnitch"
112
121
 
113
- **You're a user?** Install `aisnitch`, run `aisnitch start`, you're done.
122
+ ```bash
123
+ # Start the daemon (runs in background)
124
+ aisnitch start --daemon
114
125
 
115
- **You're building something on top?** Install `@aisnitch/client` and connect in 3 lines:
126
+ # Now connect your app to ws://127.0.0.1:4820
127
+ ```
116
128
 
117
129
  ```typescript
118
- import { createAISnitchClient, describeEvent } from '@aisnitch/client';
130
+ import { createAISnitchClient } from '@aisnitch/client';
119
131
  import WebSocket from 'ws';
120
132
 
121
133
  const client = createAISnitchClient({ WebSocketClass: WebSocket as any });
122
- client.on('event', (e) => console.log(describeEvent(e)));
123
- // "claude-code is editing code → src/index.ts [myproject]"
134
+
135
+ client.on('event', (e) => {
136
+ console.log(`${e['aisnitch.tool']}: ${e.type}`);
137
+ });
124
138
  ```
125
139
 
126
- Auto-reconnect, Zod-validated parsing, session tracking, filters, mascot state mapping — all included. See the full **[Client SDK documentation](./packages/client/README.md)**.
140
+ ### "I want a fancy web dashboard on another computer"
127
141
 
128
- ---
142
+ ```bash
143
+ aisnitch fs --daemon
144
+ # → Opens http://127.0.0.1:5174 in browser
145
+ # → Connects to daemon automatically
146
+ ```
129
147
 
130
- ## How It Works
131
-
132
- ```
133
- Claude Code ──┐
134
- OpenCode ─────┤
135
- Gemini CLI ───┤── hooks / file watchers / process detection
136
- Codex ────────┤
137
- Goose ────────┤
138
- Aider ────────┤
139
- Copilot CLI ──┤
140
- OpenClaw ─────┘
141
-
142
-
143
- ┌─────────────────┐
144
- │ AISnitch Core │
145
- │ │
146
- │ Validate (Zod) │
147
- │ Normalize │
148
- │ Enrich context │
149
- │ (terminal, cwd, │
150
- │ pid, session) │
151
- └────────┬─────────┘
152
-
153
- ┌────────┴─────────┐
154
- ▼ ▼
155
- ws://127.0.0.1:4820 TUI
156
- (your consumers) (built-in)
157
- ```
158
-
159
- Each adapter captures tool activity using the best available strategy — hooks for tools that support them (Claude Code, OpenCode, Gemini CLI), file watching for log-based tools (Codex, Aider), process detection as universal fallback. Events are validated against Zod schemas, normalized into CloudEvents, enriched with context (terminal, working directory, PID, multi-instance tracking), then pushed through an in-memory EventBus. The WebSocket server broadcasts to all connected clients with per-client ring buffers (1,000 events, oldest-first drop).
160
-
161
- **Nothing is stored on disk.** Events exist in memory during transit, then they're gone. Privacy-first by design.
148
+ ### "I want sound notifications when agents finish"
162
149
 
163
- ---
150
+ ```typescript
151
+ const client = createAISnitchClient();
164
152
 
165
- ## Architecture
166
-
167
- ```mermaid
168
- flowchart LR
169
- subgraph Tools["External AI tools"]
170
- CC["Claude Code"]
171
- OC["OpenCode"]
172
- GM["Gemini CLI"]
173
- CX["Codex"]
174
- GS["Goose"]
175
- AD["Aider"]
176
- OCL["OpenClaw"]
177
- PTY["Generic PTY"]
178
- end
179
-
180
- subgraph AIS["AISnitch runtime"]
181
- HTTP["HTTP hook receiver :4821"]
182
- UDS["UDS ingest"]
183
- REG["Adapter registry"]
184
- BUS["Typed EventBus"]
185
- WS["WebSocket server :4820"]
186
- TUI["Ink TUI"]
187
- end
188
-
189
- subgraph SDK["Consumer ecosystem"]
190
- CLIENT["@aisnitch/client SDK"]
191
- DASH["Dashboards"]
192
- SOUND["Sound engines"]
193
- MASCOT["Companions"]
194
- BOT["Bots"]
195
- end
196
-
197
- CC --> HTTP
198
- OC --> HTTP
199
- GM --> HTTP
200
- OCL --> HTTP
201
- CX --> REG
202
- GS --> REG
203
- AD --> REG
204
- PTY --> UDS
205
- HTTP --> BUS
206
- UDS --> BUS
207
- REG --> BUS
208
- BUS --> WS
209
- BUS --> TUI
210
- WS --> CLIENT
211
- CLIENT --> DASH
212
- CLIENT --> SOUND
213
- CLIENT --> MASCOT
214
- CLIENT --> BOT
153
+ client.on('event', (e) => {
154
+ if (e.type === 'task.complete') playSound('success.mp3');
155
+ if (e.type === 'agent.error') playSound('error.mp3');
156
+ if (e.type === 'agent.asking_user') playSound('ping.mp3');
157
+ });
215
158
  ```
216
159
 
217
160
  ---
218
161
 
219
- ## Supported Tools
162
+ ## 📦 Installation Options
163
+
164
+ ### npm (Recommended)
165
+
166
+ ```bash
167
+ npm i -g aisnitch
168
+ ```
169
+
170
+ ### Homebrew (macOS/Linux)
171
+
172
+ ```bash
173
+ brew install aisnitch
174
+ ```
175
+
176
+ ### From Source
177
+
178
+ ```bash
179
+ git clone https://github.com/vava-nessa/AISnitch.git
180
+ cd AISnitch
181
+ pnpm install && pnpm build
182
+ node dist/cli/index.js start
183
+ ```
220
184
 
221
- | Tool | Strategy | Setup |
222
- |---|---|---|
223
- | **Claude Code** | Command hooks + JSONL transcript watching + process detection | `aisnitch setup claude-code` |
224
- | **OpenCode** | Local plugin + process detection | `aisnitch setup opencode` |
225
- | **Gemini CLI** | Command hooks + `logs.json` watching + process detection | `aisnitch setup gemini-cli` |
226
- | **Codex** | `codex-tui.log` parsing + process detection | `aisnitch setup codex` |
227
- | **Goose** | `goosed` API polling + SSE streams + SQLite fallback | `aisnitch setup goose` |
228
- | **Copilot CLI** | Repo hooks + session-state JSONL watching | `aisnitch setup copilot-cli` |
229
- | **Aider** | `.aider.chat.history.md` watching + notifications command | `aisnitch setup aider` |
230
- | **OpenClaw** | Managed hooks + command/memory/session watchers | `aisnitch setup openclaw` |
231
- | **Any other CLI** | PTY wrapper with output heuristics | `aisnitch wrap <command>` |
185
+ ### Upgrade
232
186
 
233
- Run `aisnitch setup <tool>` to configure each tool, then `aisnitch adapters` to verify what's active.
187
+ ```bash
188
+ # npm
189
+ npm update -g aisnitch
190
+
191
+ # Homebrew
192
+ brew upgrade aisnitch
193
+ ```
234
194
 
235
195
  ---
236
196
 
237
- ## Event Model
197
+ ## 🛠️ Supported Tools
198
+
199
+ | Tool | Status | Setup Command |
200
+ |:---|:---:|:---|
201
+ | **Claude Code** | ✅ Active | `aisnitch setup claude-code` |
202
+ | **OpenCode** | ✅ Active | `aisnitch setup opencode` |
203
+ | **Gemini CLI** | ✅ Active | `aisnitch setup gemini-cli` |
204
+ | **Aider** | ✅ Active | `aisnitch setup aider` |
205
+ | **Codex** | ✅ Active | `aisnitch setup codex` |
206
+ | **Goose** | ✅ Active | `aisnitch setup goose` |
207
+ | **Copilot CLI** | ✅ Active | `aisnitch setup copilot-cli` |
208
+ | **OpenClaw** | ✅ Active | `aisnitch setup openclaw` |
209
+ | **Cursor** | ✅ Active | `aisnitch setup cursor` |
210
+ | **Zed** | ✅ Active | `aisnitch setup zed` |
211
+ | **Devin** | ✅ Active | `aisnitch setup devin` |
212
+ | **Kilo** | ✅ Active | `aisnitch setup kilo` |
213
+ | **Pi (zealncer)** | ✅ Active | `aisnitch setup pi` |
214
+ | **Any CLI** | 🔧 Fallback | `aisnitch wrap <command>` |
215
+
216
+ > 💡 Run `aisnitch adapters` to see which tools are currently connected.
238
217
 
239
- Every event is a [CloudEvents v1.0](https://cloudevents.io/) envelope with AISnitch extensions:
218
+ ---
240
219
 
241
- ```jsonc
242
- {
243
- "specversion": "1.0",
244
- "id": "019713a4-beef-7000-8000-deadbeef0042", // UUIDv7
245
- "source": "aisnitch://claude-code/myproject",
246
- "type": "agent.coding", // one of 12 types below
247
- "time": "2026-03-28T14:30:00.000Z",
220
+ ## 🔌 Web Dashboard
248
221
 
249
- "aisnitch.tool": "claude-code",
250
- "aisnitch.sessionid": "claude-code:myproject:p12345",
251
- "aisnitch.seqnum": 42,
222
+ Open a beautiful real-time dashboard in your browser:
252
223
 
253
- "data": {
254
- "state": "agent.coding",
255
- "project": "myproject",
256
- "projectPath": "/home/user/myproject",
257
- "activeFile": "src/index.ts",
258
- "toolName": "Edit",
259
- "toolInput": { "filePath": "src/index.ts" },
260
- "model": "claude-sonnet-4-5-20250514",
261
- "tokensUsed": 1500,
262
- "terminal": "iTerm2",
263
- "cwd": "/home/user/myproject",
264
- "pid": 12345,
265
- "instanceIndex": 1,
266
- "instanceTotal": 3,
267
- "errorMessage": "Rate limit exceeded", // only on agent.error
268
- "errorType": "rate_limit", // only on agent.error
269
- "raw": { /* original adapter payload */ }
270
- }
271
- }
224
+ ```bash
225
+ aisnitch fs # Open dashboard (auto-starts daemon if needed)
226
+ aisnitch fs --daemon # Start daemon + open dashboard
227
+ aisnitch fs --dashboard-port 8080 # Custom port
228
+ aisnitch fs --no-browser # Just start the server
272
229
  ```
273
230
 
274
- ### The 12 Event Types
231
+ **From another computer?** Make sure the host machine has the daemon running:
275
232
 
276
- | Type | What it means |
277
- |---|---|
278
- | `session.start` | A tool session began |
279
- | `session.end` | Session closed |
280
- | `task.start` | User submitted a prompt |
281
- | `task.complete` | Task finished |
282
- | `agent.thinking` | Model is reasoning |
283
- | `agent.streaming` | Model is generating output |
284
- | `agent.coding` | Model is editing files |
285
- | `agent.tool_call` | Model is using a tool (Bash, Grep, etc.) |
286
- | `agent.asking_user` | Waiting for human input |
287
- | `agent.idle` | No activity (120s timeout, configurable) |
288
- | `agent.error` | Something went wrong (rate limit, API error, tool failure) |
289
- | `agent.compact` | Context compaction / memory cleanup |
233
+ ```bash
234
+ aisnitch start --daemon # Start on host machine first
235
+ aisnitch fs # Connect from any browser
236
+ ```
290
237
 
291
238
  ---
292
239
 
293
- ## Build on Top of AISnitch
240
+ ## 📡 WebSocket API (Build Anything)
294
241
 
295
- The whole point of AISnitch is to be a platform. Here are 5 things you can build with the [`@aisnitch/client`](./packages/client/README.md) SDK:
242
+ AISnitch exposes a WebSocket stream at `ws://127.0.0.1:4820`. Connect with the SDK:
296
243
 
297
- ### Live Dashboard
244
+ ### Install the SDK
245
+
246
+ ```bash
247
+ pnpm add @aisnitch/client zod
248
+ ```
249
+
250
+ ### Basic Usage
298
251
 
299
252
  ```typescript
300
253
  import { createAISnitchClient, describeEvent } from '@aisnitch/client';
@@ -302,274 +255,351 @@ import WebSocket from 'ws';
302
255
 
303
256
  const client = createAISnitchClient({ WebSocketClass: WebSocket as any });
304
257
 
305
- client.on('connected', (w) => {
306
- console.log(`Connected to AISnitch v${w.version}`);
307
- console.log(`Active tools: ${w.activeTools.join(', ')}`);
258
+ // Get notified when connected
259
+ client.on('connected', (info) => {
260
+ console.log(`Connected to AISnitch ${info.version}`);
261
+ console.log(`Tools: ${info.activeTools.join(', ')}`);
308
262
  });
309
263
 
310
- client.on('event', (e) => {
311
- const line = describeEvent(e);
312
- console.log(`[${e['aisnitch.tool']}] ${line}`);
264
+ // Receive all events
265
+ client.on('event', (event) => {
266
+ console.log(describeEvent(event));
267
+ // → "claude-code is thinking... → user auth module"
268
+ // → "opencode is coding... → src/api/users.ts"
313
269
  });
314
270
 
315
- // Track all active sessions
271
+ // Track sessions
316
272
  setInterval(() => {
317
273
  const sessions = client.sessions?.getAll() ?? [];
318
- console.log(`\n--- ${sessions.length} active session(s) ---`);
319
- for (const s of sessions) {
320
- console.log(` ${s.tool} → ${s.lastActivity} (${s.eventCount} events)`);
321
- }
274
+ console.log(`${sessions.length} active sessions`);
322
275
  }, 5000);
323
276
  ```
324
277
 
325
- ### Sound Notifications (PeonPing-style)
278
+ ### Sound Notifications
326
279
 
327
280
  ```typescript
328
- import { createAISnitchClient, filters } from '@aisnitch/client';
329
-
330
- const client = createAISnitchClient({ WebSocketClass: WebSocket as any });
331
-
332
- const SOUNDS: Record<string, string> = {
333
- 'session.start': 'boot.mp3',
334
- 'task.complete': 'success.mp3',
335
- 'agent.asking_user': 'alert.mp3',
336
- 'agent.error': 'error.mp3',
337
- 'agent.coding': 'keyboard.mp3',
281
+ import { createAISnitchClient } from '@aisnitch/client';
282
+
283
+ const SOUNDS = {
284
+ 'session.start': 'sounds/boot.mp3',
285
+ 'task.complete': 'sounds/done.mp3',
286
+ 'agent.asking_user': 'sounds/ping.mp3',
287
+ 'agent.error': 'sounds/error.mp3',
288
+ 'agent.coding': 'sounds/keyboard.mp3',
338
289
  };
339
290
 
340
- client.on('event', (e) => {
341
- const sound = SOUNDS[e.type];
342
- if (sound) playSound(`./sounds/${sound}`);
343
- });
344
- ```
345
-
346
- ### Animated Mascot / Companion
347
-
348
- ```typescript
349
- import { createAISnitchClient, eventToMascotState } from '@aisnitch/client';
350
-
351
291
  const client = createAISnitchClient();
352
-
353
292
  client.on('event', (e) => {
354
- const state = eventToMascotState(e);
355
- // state.mood → 'thinking' | 'working' | 'celebrating' | 'panicking' | ...
356
- // state.animation → 'ponder' | 'type' | 'dance' | 'shake' | ...
357
- // state.color → '#a855f7' (hex)
358
- // state.label → 'Thinking...'
359
- // state.detail → 'src/index.ts' (optional)
360
- updateMySprite(state);
293
+ if (SOUNDS[e.type]) playSound(SOUNDS[e.type]);
361
294
  });
362
295
  ```
363
296
 
364
- ### Slack / Discord Bot
297
+ ### Slack/Discord Bot
365
298
 
366
299
  ```typescript
367
- import { createAISnitchClient, filters, formatStatusLine } from '@aisnitch/client';
368
- import WebSocket from 'ws';
300
+ import { createAISnitchClient, formatStatusLine } from '@aisnitch/client';
369
301
 
370
- const client = createAISnitchClient({ WebSocketClass: WebSocket as any });
302
+ const client = createAISnitchClient();
371
303
 
372
- // Only notify on events that need attention
373
304
  client.on('event', (e) => {
374
- if (filters.needsAttention(e)) {
375
- postToSlack(`⚠️ ${formatStatusLine(e)}`);
305
+ // Notify on important events
306
+ if (e.type === 'agent.error') {
307
+ postToSlack(`🔴 Error: ${formatStatusLine(e)}`);
376
308
  }
377
-
378
309
  if (e.type === 'task.complete') {
379
- postToSlack(`✅ ${formatStatusLine(e)}`);
310
+ postToDiscord(`✅ Done: ${formatStatusLine(e)}`);
380
311
  }
381
312
  });
382
313
  ```
383
314
 
384
- ### Menu Bar Widget (Electron / Tauri)
315
+ ### Direct WebSocket (No SDK)
385
316
 
386
- ```typescript
387
- import { createAISnitchClient, formatStatusLine } from '@aisnitch/client';
317
+ ```bash
318
+ # See raw events in one line
319
+ node -e "
320
+ const WebSocket = require('ws');
321
+ const ws = new WebSocket('ws://127.0.0.1:4820');
322
+ ws.on('message', m => console.log(JSON.parse(m.toString()).type));
323
+ "
324
+ ```
388
325
 
389
- const client = createAISnitchClient();
390
- let sessionCounter = 0;
391
- const sessionMap = new Map<string, number>();
326
+ ---
392
327
 
393
- client.on('event', (e) => {
394
- if (!sessionMap.has(e['aisnitch.sessionid'])) {
395
- sessionMap.set(e['aisnitch.sessionid'], ++sessionCounter);
396
- }
397
- const num = sessionMap.get(e['aisnitch.sessionid'])!;
328
+ ## ⌨️ CLI Reference
398
329
 
399
- // Update your menu bar / tray icon
400
- tray.setTitle(formatStatusLine(e, num));
401
- tray.setToolTip(`${client.sessions?.count ?? 0} active sessions`);
402
- });
330
+ ### Dashboard & TUI
331
+
332
+ ```bash
333
+ aisnitch start # Open TUI dashboard
334
+ aisnitch start --tool claude-code # Filter by tool
335
+ aisnitch start --type agent.coding # Filter by event type
336
+ aisnitch start --view full-data # Show full JSON
403
337
  ```
404
338
 
405
- For complete API docs, React/Vue hooks, filters, TypeScript integration, and more examples, see the **[Client SDK README](./packages/client/README.md)**.
339
+ ### Web Dashboard
406
340
 
407
- <details>
408
- <summary>Raw WebSocket (without SDK)</summary>
341
+ ```bash
342
+ aisnitch fs # Open web dashboard
343
+ aisnitch fs --daemon # Start daemon + open
344
+ aisnitch fs --dashboard-port 8080 # Custom port
345
+ aisnitch fs --no-browser # Server only
346
+ ```
409
347
 
410
- If you don't want the SDK, you can connect directly:
348
+ ### Daemon Management
411
349
 
412
350
  ```bash
413
- # One-liner to see raw events
414
- node -e "
415
- const WebSocket = require('ws');
416
- const ws = new WebSocket('ws://127.0.0.1:4820');
417
- ws.on('message', m => {
418
- const e = JSON.parse(m.toString());
419
- if (e.type !== 'welcome') console.log(e.type, e['aisnitch.tool'], e.data?.project);
420
- });
421
- "
351
+ aisnitch start --daemon # Start daemon in background
352
+ aisnitch status # Check daemon status
353
+ aisnitch attach # Attach TUI to running daemon
354
+ aisnitch stop # Stop daemon
422
355
  ```
423
356
 
424
- The first message is always a `welcome` payload with version, active tools, and uptime. Every subsequent message is a CloudEvents event as described above.
357
+ ### Tool Setup
425
358
 
426
- </details>
359
+ ```bash
360
+ aisnitch setup claude-code # Configure tool
361
+ aisnitch setup opencode
362
+ aisnitch setup aider
363
+ aisnitch setup claude-code --revert # Remove configuration
364
+ ```
427
365
 
428
- ### Health Check
366
+ ### Utilities
429
367
 
430
368
  ```bash
431
- curl http://127.0.0.1:4821/health
369
+ aisnitch adapters # Show enabled tools
370
+ aisnitch logger # Stream raw events (no TUI)
371
+ aisnitch mock claude-code # Simulate events
372
+ aisnitch mock all --speed 2 # Demo mode (2x speed)
373
+ aisnitch wrap aider --model sonnet # Wrap any CLI
374
+ aisnitch setup claude-code # Run setup wizard
375
+ aisnitch self-update # Update AISnitch
432
376
  ```
433
377
 
434
- ```json
435
- {
436
- "status": "ok",
437
- "uptime": 3600,
438
- "consumers": 2,
439
- "events": 1542,
440
- "droppedEvents": 0
441
- }
442
- ```
378
+ ---
379
+
380
+ ## 🖥️ TUI Controls
381
+
382
+ | Key | Action |
383
+ |:---:|:---|
384
+ | `q` / `Ctrl+C` | Quit |
385
+ | `d` | Toggle daemon |
386
+ | `r` | Refresh |
387
+ | `v` | Toggle JSON inspector |
388
+ | `f` | Filter by tool |
389
+ | `t` | Filter by event type |
390
+ | `/` | Search |
391
+ | `Esc` | Clear filters |
392
+ | `Space` | Freeze/resume |
393
+ | `c` | Clear buffer |
394
+ | `?` | Help |
395
+ | `Tab` | Switch panel |
396
+ | `↑↓` / `jk` | Navigate |
397
+ | `[]` | Page inspector |
443
398
 
444
399
  ---
445
400
 
446
- ## CLI Reference
401
+ ## 🏗️ Architecture
447
402
 
448
- ```bash
449
- # Dashboard mode (always opens the TUI)
450
- aisnitch start
451
- aisnitch start --tool claude-code # pre-filter by tool
452
- aisnitch start --type agent.coding # pre-filter by event type
453
- aisnitch start --view full-data # expanded JSON inspector
403
+ ```
404
+ ┌─────────────────────────────────────────────────────────────────┐
405
+ │ External AI Tools │
406
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
407
+ │ │ Claude │ OpenCode Gemini │ │ Aider │ ... │
408
+ │ │ Code │ │ │ │ CLI │ │ │ │
409
+ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
410
+ │ │ │ │ │ │
411
+ │ └────────────┴────────────┴────────────┘ │
412
+ │ │ │
413
+ │ ▼ │
414
+ │ ┌───────────────────┐ │
415
+ │ │ HTTP Receiver │ │
416
+ │ │ :4821 │ │
417
+ │ └─────────┬─────────┘ │
418
+ │ │ │
419
+ │ ▼ │
420
+ │ ┌───────────────────┐ │
421
+ │ │ EventBus │ │
422
+ │ │ (validation + │ │
423
+ │ │ normalization) │ │
424
+ │ └─────────┬─────────┘ │
425
+ │ │ │
426
+ │ ┌─────────────┼─────────────┐ │
427
+ │ ▼ │ ▼ │
428
+ │ ┌─────────────┐ │ ┌─────────────┐ │
429
+ │ │ WebSocket │ │ │ TUI │ │
430
+ │ │ :4820 │ │ │ Dashboard │ │
431
+ │ └──────┬──────┘ │ └─────────────┘ │
432
+ │ │ │ │
433
+ │ ▼ ▼ │
434
+ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
435
+ │ │ Client │ │ Sound │ │ Mascot │ │
436
+ │ │ Dashboard │ │ Engine │ │ Companion │ │
437
+ │ └─────────────┘ └─────────────┘ └─────────────┘ │
438
+ └─────────────────────────────────────────────────────────────────┘
439
+ ```
454
440
 
455
- # Fullscreen web dashboard (from another computer)
456
- aisnitch fs # open dashboard in browser
457
- aisnitch fs --daemon # start daemon automatically if not running
458
- aisnitch fs --dashboard-port 8080 # use different port
459
- aisnitch fs --no-browser # just start the server
441
+ ### Key Points
460
442
 
461
- # Background daemon
462
- aisnitch start --daemon
463
- aisnitch status # check if daemon is running
464
- aisnitch attach # open TUI attached to running daemon
465
- aisnitch stop # kill daemon
443
+ - **Zero storage**: Events live in memory only, never written to disk
444
+ - **Privacy-first**: No data leaves your machine
445
+ - **Multi-instance tracking**: Handles multiple sessions of the same tool
446
+ - **Auto-reconnect**: SDK handles reconnection automatically
447
+ - **Zod validation**: All events validated before processing
466
448
 
467
- # Raw event logger (no TUI, full payload)
468
- aisnitch logger
449
+ ---
469
450
 
470
- # Tool setup (run once per tool)
471
- aisnitch setup claude-code
472
- aisnitch setup opencode
473
- aisnitch setup gemini-cli
474
- aisnitch setup codex
475
- aisnitch setup goose
476
- aisnitch setup copilot-cli
477
- aisnitch setup aider
478
- aisnitch setup openclaw
479
- aisnitch setup claude-code --revert # undo setup
451
+ ## 📊 Event Model
480
452
 
481
- # Check enabled adapters
482
- aisnitch adapters
453
+ Every event follows [CloudEvents v1.0](https://cloudevents.io/) format:
483
454
 
484
- # Demo mode (simulated events)
485
- aisnitch mock claude-code --speed 2 --duration 20
486
- aisnitch start --mock all
455
+ ```json
456
+ {
457
+ "specversion": "1.0",
458
+ "id": "019713a4-beef-7000-8000-deadbeef0042",
459
+ "source": "aisnitch://claude-code/myproject",
460
+ "type": "agent.coding",
461
+ "time": "2026-03-28T14:30:00.000Z",
487
462
 
488
- # PTY wrapper (any unsupported CLI)
489
- aisnitch wrap aider --model sonnet
490
- aisnitch wrap goose session
491
- ```
463
+ "aisnitch.tool": "claude-code",
464
+ "aisnitch.sessionid": "claude-code:myproject:p12345",
465
+ "aisnitch.seqnum": 42,
492
466
 
493
- ---
467
+ "data": {
468
+ "state": "agent.coding",
469
+ "project": "myproject",
470
+ "projectPath": "/home/user/myproject",
471
+ "activeFile": "src/index.ts",
472
+ "toolName": "Edit",
473
+ "model": "claude-sonnet-4-20250514",
474
+ "tokensUsed": 1500,
475
+ "inputTokens": 450,
476
+ "outputTokens": 1050,
477
+ "terminal": "iTerm2",
478
+ "cwd": "/home/user/myproject"
479
+ }
480
+ }
481
+ ```
494
482
 
495
- ## TUI Keybinds
483
+ ### Event Types
496
484
 
497
- | Key | Action |
498
- |---|---|
499
- | `q` / `Ctrl+C` | Quit |
500
- | `d` | Start / stop the daemon |
501
- | `r` | Refresh daemon status |
502
- | `v` | Toggle full-data JSON inspector |
503
- | `f` | Tool filter picker |
504
- | `t` | Event type filter picker |
505
- | `/` | Free-text search |
506
- | `Esc` | Clear all filters |
507
- | `Space` | Freeze / resume live tailing |
508
- | `c` | Clear event buffer |
509
- | `?` | Help overlay |
510
- | `Tab` | Switch panel focus |
511
- | `↑↓` / `jk` | Navigate rows |
512
- | `[` `]` | Page inspector up / down |
485
+ | Type | Description |
486
+ |:---|:---|
487
+ | `session.start` | Tool started |
488
+ | `session.end` | Tool closed |
489
+ | `task.start` | User submitted prompt |
490
+ | `task.complete` | Task finished |
491
+ | `agent.thinking` | Model reasoning |
492
+ | `agent.streaming` | Output being generated |
493
+ | `agent.coding` | Editing files |
494
+ | `agent.tool_call` | Using Bash, Grep, etc. |
495
+ | `agent.asking_user` | Waiting for input |
496
+ | `agent.idle` | No activity (2+ min) |
497
+ | `agent.error` | Error occurred |
498
+ | `agent.compact` | Context cleanup |
513
499
 
514
500
  ---
515
501
 
516
- ## Config Reference
502
+ ## 📁 File Structure
517
503
 
518
- AISnitch state lives under `~/.aisnitch/` (override with `AISNITCH_HOME`).
504
+ ```
505
+ ~/.aisnitch/
506
+ ├── config.json # Your configuration
507
+ ├── aisnitch.pid # Daemon PID
508
+ ├── daemon-state.json # Connection info
509
+ ├── daemon.log # Daemon logs (5MB max)
510
+ └── aisnitch.sock # Unix socket (IPC)
511
+ ```
519
512
 
520
- | Path | Purpose |
521
- |---|---|
522
- | `config.json` | User configuration |
523
- | `aisnitch.pid` | Daemon PID file |
524
- | `daemon-state.json` | Daemon connection info |
525
- | `daemon.log` | Daemon output log (5 MB max) |
526
- | `aisnitch.sock` | Unix domain socket (IPC) |
513
+ ### Ports
527
514
 
528
515
  | Port | Purpose |
529
- |---|---|
530
- | `4820` | WebSocket stream (consumers connect here) |
531
- | `4821` | HTTP hook receiver + `/health` endpoint |
516
+ |:---:|:---|
517
+ | `4820` | WebSocket (connect here) |
518
+ | `4821` | HTTP webhook receiver + health |
519
+
520
+ ### Health Check
521
+
522
+ ```bash
523
+ curl http://127.0.0.1:4821/health
524
+ ```
532
525
 
533
526
  ---
534
527
 
535
- ## Development
528
+ ## 🧪 Development
536
529
 
537
530
  ```bash
531
+ # Setup
532
+ git clone https://github.com/vava-nessa/AISnitch.git
533
+ cd AISnitch
538
534
  pnpm install
539
- pnpm build # ESM + CJS + .d.ts (main + client SDK)
540
- pnpm lint # ESLint
541
- pnpm typecheck # tsc --noEmit
542
- pnpm test # Vitest (156 tests)
543
- pnpm test:coverage
544
- pnpm test:e2e # requires opencode installed
545
535
 
546
- # Client SDK only
547
- pnpm --filter @aisnitch/client build
548
- pnpm --filter @aisnitch/client test # 48 tests
536
+ # Build
537
+ pnpm build # ESM + CJS + TypeScript types
538
+
539
+ # Quality
540
+ pnpm lint # ESLint
541
+ pnpm typecheck # TypeScript
542
+ pnpm test # 300+ tests
543
+ pnpm test:coverage # Coverage report
549
544
  ```
550
545
 
551
- Project structure:
546
+ ### Project Structure
552
547
 
553
548
  ```
554
- aisnitch/ # main package — daemon, CLI, TUI, adapters
549
+ aisnitch/
555
550
  ├── src/
556
- │ ├── adapters/ # 13 adapter implementations
557
- │ ├── cli/ # commander commands
558
- │ ├── core/ # events, pipeline, config
559
- │ └── tui/ # Ink dashboard
551
+ │ ├── adapters/ # 13 tool adapters
552
+ │ ├── cli/ # Commander CLI
553
+ │ ├── core/ # Events, pipeline, config
554
+ │ └── tui/ # Ink terminal dashboard
560
555
  ├── packages/
561
- │ └── client/ # @aisnitch/client SDK
562
- │ └── src/ # types, client, sessions, filters, helpers
563
- ├── docs/ # technical documentation
564
- └── tasks/ # kanban task board
556
+ │ └── client/ # @aisnitch/client SDK
557
+ ├── docs/ # Technical docs
558
+ └── tasks/ # Task board
565
559
  ```
566
560
 
567
- Docs: [`docs/index.md`](./docs/index.md) | Tasks: [`tasks/tasks.md`](./tasks/tasks.md)
561
+ ---
562
+
563
+ ## 📚 Resources
568
564
 
569
- Contributing: [`CONTRIBUTING.md`](./CONTRIBUTING.md) | [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md)
565
+ - [Documentation](./docs/index.md) Technical details
566
+ - [Client SDK](./packages/client/README.md) — Build on top
567
+ - [Tasks](./tasks/tasks.md) — What's being worked on
568
+ - [Contributing](./CONTRIBUTING.md) — How to contribute
570
569
 
571
570
  ---
572
571
 
573
- ## License
572
+ ## ❓ FAQ
573
+
574
+ **Q: Does AISnitch store my data?**
575
+
576
+ No. Events transit through memory only and are never written to disk. Nothing leaves your machine.
577
+
578
+ **Q: Which tools are supported?**
579
+
580
+ 13 tools out of the box: Claude Code, OpenCode, Gemini CLI, Aider, Codex, Goose, Copilot CLI, OpenClaw, Cursor, Zed, Devin, Kilo, Pi. Plus any CLI via the `wrap` command.
574
581
 
575
- Apache-2.0, © [Vanessa Depraute / vava-nessa](https://github.com/vava-nessa).
582
+ **Q: Can I build my own dashboard?**
583
+
584
+ Yes! Use the `@aisnitch/client` SDK or connect directly to `ws://127.0.0.1:4820`.
585
+
586
+ **Q: How do I update AISnitch?**
587
+
588
+ ```bash
589
+ npm update -g aisnitch # npm
590
+ brew upgrade aisnitch # Homebrew
591
+ ```
592
+
593
+ **Q: Why "Snitch"?**
594
+
595
+ Because it snitches on your AI agents — tells you what they're doing! 🎭
596
+
597
+ ---
598
+
599
+ ## 📜 License
600
+
601
+ Apache-2.0 — [Vanessa Depraute](https://github.com/vava-nessa)
602
+
603
+ [![CI](https://github.com/vava-nessa/AISnitch/actions/workflows/ci.yml/badge.svg)](https://github.com/vava-nessa/AISnitch/actions/workflows/ci.yml)
604
+ [![npm](https://img.shields.io/npm/v/aisnitch?logo=npm)](https://www.npmjs.com/package/aisnitch)
605
+ [![Node >=20](https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js)](https://nodejs.org/)
@@ -771,7 +771,7 @@ var import_commander = require("commander");
771
771
 
772
772
  // src/package-info.ts
773
773
  var AISNITCH_PACKAGE_NAME = "aisnitch";
774
- var AISNITCH_VERSION = "0.2.22";
774
+ var AISNITCH_VERSION = "0.2.23";
775
775
  var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
776
776
 
777
777
  // src/core/events/schema.ts
package/dist/cli/index.js CHANGED
@@ -743,7 +743,7 @@ import { Command, InvalidArgumentError } from "commander";
743
743
 
744
744
  // src/package-info.ts
745
745
  var AISNITCH_PACKAGE_NAME = "aisnitch";
746
- var AISNITCH_VERSION = "0.2.22";
746
+ var AISNITCH_VERSION = "0.2.23";
747
747
  var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
748
748
 
749
749
  // src/core/events/schema.ts
package/dist/index.cjs CHANGED
@@ -9446,7 +9446,7 @@ var import_ws = require("ws");
9446
9446
 
9447
9447
  // src/package-info.ts
9448
9448
  var AISNITCH_PACKAGE_NAME = "aisnitch";
9449
- var AISNITCH_VERSION = "0.2.22";
9449
+ var AISNITCH_VERSION = "0.2.23";
9450
9450
  var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
9451
9451
  function getPackageScaffoldInfo() {
9452
9452
  return {
package/dist/index.js CHANGED
@@ -9246,7 +9246,7 @@ import { WebSocket, WebSocketServer } from "ws";
9246
9246
 
9247
9247
  // src/package-info.ts
9248
9248
  var AISNITCH_PACKAGE_NAME = "aisnitch";
9249
- var AISNITCH_VERSION = "0.2.22";
9249
+ var AISNITCH_VERSION = "0.2.23";
9250
9250
  var AISNITCH_DESCRIPTION = "Universal bridge for AI coding tool activity \u2014 capture, normalize, stream.";
9251
9251
  function getPackageScaffoldInfo() {
9252
9252
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aisnitch",
3
- "version": "0.2.22",
3
+ "version": "0.2.23",
4
4
  "description": "Universal bridge for AI coding tool activity — capture, normalize, and stream live tool events.",
5
5
  "keywords": [
6
6
  "ai",