claude-live 0.4.8 → 1.1.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.
Files changed (53) hide show
  1. package/bin/claude-live.js +36 -20
  2. package/package.json +13 -26
  3. package/.claude-plugin/hooks/hooks.json +0 -126
  4. package/.claude-plugin/marketplace.json +0 -27
  5. package/.claude-plugin/plugin.json +0 -14
  6. package/README.md +0 -60
  7. package/bin/check-and-restart.js +0 -63
  8. package/bin/send-hook.sh +0 -34
  9. package/bin/start-server.sh +0 -33
  10. package/client/dist/assets/index-B1BUdq7a.js +0 -47
  11. package/client/dist/assets/index-DjcKbX6b.css +0 -1
  12. package/client/dist/chords/chord_01.wav +0 -0
  13. package/client/dist/chords/chord_02.wav +0 -0
  14. package/client/dist/chords/chord_03.wav +0 -0
  15. package/client/dist/chords/chord_04.wav +0 -0
  16. package/client/dist/chords/chord_05.wav +0 -0
  17. package/client/dist/chords/chord_06.wav +0 -0
  18. package/client/dist/chords/chord_07.wav +0 -0
  19. package/client/dist/chords/chord_08.wav +0 -0
  20. package/client/dist/chords/chord_09.wav +0 -0
  21. package/client/dist/chords/chord_10.wav +0 -0
  22. package/client/dist/chords/chord_11.wav +0 -0
  23. package/client/dist/chords/chord_12.wav +0 -0
  24. package/client/dist/chords/chord_13.wav +0 -0
  25. package/client/dist/chords/chord_14.wav +0 -0
  26. package/client/dist/chords/chord_15.wav +0 -0
  27. package/client/dist/chords/chord_16.wav +0 -0
  28. package/client/dist/index.html +0 -18
  29. package/client/public/chords/chord_01.wav +0 -0
  30. package/client/public/chords/chord_02.wav +0 -0
  31. package/client/public/chords/chord_03.wav +0 -0
  32. package/client/public/chords/chord_04.wav +0 -0
  33. package/client/public/chords/chord_05.wav +0 -0
  34. package/client/public/chords/chord_06.wav +0 -0
  35. package/client/public/chords/chord_07.wav +0 -0
  36. package/client/public/chords/chord_08.wav +0 -0
  37. package/client/public/chords/chord_09.wav +0 -0
  38. package/client/public/chords/chord_10.wav +0 -0
  39. package/client/public/chords/chord_11.wav +0 -0
  40. package/client/public/chords/chord_12.wav +0 -0
  41. package/client/public/chords/chord_13.wav +0 -0
  42. package/client/public/chords/chord_14.wav +0 -0
  43. package/client/public/chords/chord_15.wav +0 -0
  44. package/client/public/chords/chord_16.wav +0 -0
  45. package/commands/claude-live.md +0 -145
  46. package/hooks/hooks.json +0 -166
  47. package/server/index.js +0 -288
  48. package/test-agent-animations-long.js +0 -144
  49. package/test-agent-animations.js +0 -126
  50. package/test-agents.js +0 -61
  51. package/tests/server.test.js +0 -48
  52. package/tests/store.test.ts +0 -141
  53. package/vitest.config.ts +0 -10
@@ -1,26 +1,42 @@
1
1
  #!/usr/bin/env node
2
- import { createServer } from '../server/index.js'
3
- import open from 'open'
2
+ import { execFileSync } from "child_process";
3
+ import { createRequire } from "module";
4
+ import { join } from "path";
4
5
 
5
- const portArgIdx = process.argv.findIndex(a => a === '--port' || a.startsWith('--port='))
6
- const portArg = portArgIdx >= 0
7
- ? (process.argv[portArgIdx].includes('=') ? process.argv[portArgIdx].split('=')[1] : process.argv[portArgIdx + 1])
8
- : '43451'
9
- const port = parseInt(portArg, 10)
6
+ const PLATFORMS = {
7
+ "linux-x64": "@claude-live/linux-x64",
8
+ "linux-arm64": "@claude-live/linux-arm64",
9
+ "darwin-x64": "@claude-live/darwin-x64",
10
+ "darwin-arm64": "@claude-live/darwin-arm64",
11
+ "win32-x64": "@claude-live/win32-x64",
12
+ };
13
+
14
+ const key = `${process.platform}-${process.arch}`;
15
+ const pkg = PLATFORMS[key];
16
+
17
+ if (!pkg) {
18
+ console.error(`Unsupported platform: ${key}`);
19
+ console.error(`Supported: ${Object.keys(PLATFORMS).join(", ")}`);
20
+ process.exit(1);
21
+ }
22
+
23
+ const require = createRequire(import.meta.url);
24
+ let binPath;
25
+ try {
26
+ const pkgDir = join(require.resolve(`${pkg}/package.json`), "..");
27
+ const ext = process.platform === "win32" ? ".exe" : "";
28
+ binPath = join(pkgDir, `bin/claude-live${ext}`);
29
+ } catch {
30
+ console.error(`Platform package ${pkg} not installed.`);
31
+ console.error(`Try: npm install ${pkg}`);
32
+ process.exit(1);
33
+ }
10
34
 
11
35
  try {
12
- await createServer({ port })
13
- const url = `http://localhost:${port}`
14
- console.log(`claude-live running at ${url}`)
15
- open(url)
36
+ const result = execFileSync(binPath, process.argv.slice(2), {
37
+ stdio: "inherit",
38
+ env: { ...process.env, CLAUDE_LIVE_STATIC_DIR: join(binPath, "../../client/dist") },
39
+ });
16
40
  } catch (e) {
17
- if (e.code === 'EADDRINUSE') {
18
- console.error(`Port ${port} is already in use.`)
19
- console.error(`Either claude-live is already running, or another process is using port ${port}.`)
20
- console.error(`Check: curl http://localhost:${port}/buffer`)
21
- process.exit(1)
22
- } else {
23
- console.error(e)
24
- process.exit(1)
25
- }
41
+ process.exit(e.status ?? 1);
26
42
  }
package/package.json CHANGED
@@ -1,34 +1,21 @@
1
1
  {
2
2
  "name": "claude-live",
3
- "version": "0.4.8",
3
+ "version": "1.1.1",
4
4
  "description": "Realtime Claude Code activity visualizer",
5
+ "license": "MIT",
6
+ "repository": "https://github.com/marisancans/claude-live",
5
7
  "bin": {
6
- "claude-live": "./bin/claude-live.js"
8
+ "claude-live": "bin/claude-live.js"
7
9
  },
8
- "scripts": {
9
- "dev": "concurrently \"node server/index.js\" \"cd client && vite dev\"",
10
- "build": "cd client && vite build",
11
- "start": "node server/index.js",
12
- "test": "vitest run",
13
- "prepublishOnly": "npm run build"
14
- },
15
- "dependencies": {
16
- "express": "^4.18.2",
17
- "matter-js": "^0.20.0",
18
- "open": "^10.1.0",
19
- "uuid": "^9.0.0"
20
- },
21
- "devDependencies": {
22
- "@types/react": "^18.2.0",
23
- "@types/react-dom": "^18.2.0",
24
- "@vitejs/plugin-react": "^4.2.0",
25
- "concurrently": "^8.2.0",
26
- "pixi.js": "^7.4.0",
27
- "react": "^18.2.0",
28
- "react-dom": "^18.2.0",
29
- "typescript": "^5.3.0",
30
- "vite": "^5.1.0",
31
- "vitest": "^1.3.0"
10
+ "files": [
11
+ "bin/"
12
+ ],
13
+ "optionalDependencies": {
14
+ "@claude-live/linux-x64": "1.1.1",
15
+ "@claude-live/linux-arm64": "1.1.1",
16
+ "@claude-live/darwin-x64": "1.1.1",
17
+ "@claude-live/darwin-arm64": "1.1.1",
18
+ "@claude-live/win32-x64": "1.1.1"
32
19
  },
33
20
  "type": "module",
34
21
  "engines": {
@@ -1,126 +0,0 @@
1
- {
2
- "description": "claude-live hooks — forwards Claude Code events to the visualizer server",
3
- "hooks": {
4
- "SessionStart": [{
5
- "hooks": [
6
- {
7
- "type": "command",
8
- "command": "curl -sf http://localhost:43451/buffer >/dev/null 2>&1 || (npx claude-live@latest >/tmp/claude-live.log 2>&1 &)",
9
- "async": true
10
- },
11
- {
12
- "type": "command",
13
- "command": "bin/send-hook.sh",
14
- "async": true
15
- }
16
- ]
17
- }],
18
- "InstructionsLoaded": [{
19
- "hooks": [{
20
- "type": "command",
21
- "command": "bin/send-hook.sh",
22
- "async": true
23
- }]
24
- }],
25
- "WorktreeCreate": [{
26
- "hooks": [{
27
- "type": "command",
28
- "command": "bin/send-hook.sh",
29
- "async": true
30
- }]
31
- }],
32
- "WorktreeRemove": [{
33
- "hooks": [{
34
- "type": "command",
35
- "command": "bin/send-hook.sh",
36
- "async": true
37
- }]
38
- }],
39
- "PreToolUse": [{
40
- "hooks": [{
41
- "type": "command",
42
- "command": "bin/send-hook.sh",
43
- "async": true
44
- }]
45
- }],
46
- "PostToolUse": [{
47
- "hooks": [{
48
- "type": "command",
49
- "command": "bin/send-hook.sh",
50
- "async": true
51
- }]
52
- }],
53
- "Stop": [{
54
- "hooks": [{
55
- "type": "command",
56
- "command": "bin/send-hook.sh",
57
- "async": true
58
- }]
59
- }],
60
- "Notification": [{
61
- "hooks": [{
62
- "type": "command",
63
- "command": "bin/send-hook.sh",
64
- "async": true
65
- }]
66
- }],
67
- "PermissionRequest": [{
68
- "hooks": [{
69
- "type": "command",
70
- "command": "bin/send-hook.sh",
71
- "async": true
72
- }]
73
- }],
74
- "SubagentStart": [{
75
- "hooks": [{
76
- "type": "command",
77
- "command": "bin/send-hook.sh",
78
- "async": true
79
- }]
80
- }],
81
- "SubagentStop": [{
82
- "hooks": [{
83
- "type": "command",
84
- "command": "bin/send-hook.sh",
85
- "async": true
86
- }]
87
- }],
88
- "SessionEnd": [{
89
- "hooks": [{
90
- "type": "command",
91
- "command": "bin/send-hook.sh",
92
- "async": true
93
- }]
94
- }],
95
- "PostToolUseFailure": [{
96
- "hooks": [{
97
- "type": "command",
98
- "command": "bin/send-hook.sh",
99
- "async": true
100
- }]
101
- }],
102
- "UserPromptSubmit": [{
103
- "hooks": [{
104
- "type": "command",
105
- "command": "bin/send-hook.sh",
106
- "async": true
107
- }]
108
- }],
109
- "PreCompact": [{
110
- "match": { "trigger": ["manual", "auto"] },
111
- "hooks": [{
112
- "type": "command",
113
- "command": "bin/send-hook.sh",
114
- "async": true
115
- }]
116
- }],
117
- "PostCompact": [{
118
- "match": { "trigger": ["manual", "auto"] },
119
- "hooks": [{
120
- "type": "command",
121
- "command": "bin/send-hook.sh",
122
- "async": true
123
- }]
124
- }]
125
- }
126
- }
@@ -1,27 +0,0 @@
1
- {
2
- "name": "claude-live",
3
- "owner": {
4
- "name": "marisancans"
5
- },
6
- "metadata": {
7
- "description": "Realtime solar system visualizer for Claude Code sessions"
8
- },
9
- "plugins": [
10
- {
11
- "name": "claude-live",
12
- "source": "./",
13
- "description": "Watch your Claude Code sessions rendered as a living solar system. Files orbit as planets, operations fire directional lasers, parallel sessions glow as separate star clusters.",
14
- "author": {
15
- "name": "marisancans"
16
- },
17
- "category": "development",
18
- "keywords": [
19
- "visualizer",
20
- "activity",
21
- "realtime",
22
- "orbit",
23
- "solar-system"
24
- ]
25
- }
26
- ]
27
- }
@@ -1,14 +0,0 @@
1
- {
2
- "name": "claude-live",
3
- "description": "Realtime solar system visualizer for Claude Code sessions",
4
- "author": {
5
- "name": "marisancans"
6
- },
7
- "repository": "https://github.com/marisancans/claude-live",
8
- "keywords": [
9
- "visualizer",
10
- "activity",
11
- "realtime",
12
- "orbit"
13
- ]
14
- }
package/README.md DELETED
@@ -1,60 +0,0 @@
1
- # claude-live
2
-
3
- Realtime solar system visualization of Claude Code activity. Files orbit as planets, operations fire directional lasers, sessions glow as separate star systems.
4
-
5
- ## Install as Plugin (Recommended)
6
-
7
- ```bash
8
- claude plugin marketplace add marisancans/claude-live
9
- ```
10
-
11
- Hooks are configured automatically. Open `http://localhost:43451` during a Claude Code session.
12
-
13
- ## Manual Setup
14
-
15
- Start the server:
16
-
17
- ```bash
18
- npx claude-live
19
- ```
20
-
21
- Add to `~/.claude/settings.json`:
22
-
23
- ```json
24
- {
25
- "hooks": {
26
- "PreToolUse": [{"hooks":[{"type":"command","command":"curl -sf -X POST http://localhost:43451/hook -H 'Content-Type: application/json' -d @- 2>/dev/null || true","async":true}]}],
27
- "PostToolUse": [{"hooks":[{"type":"command","command":"curl -sf -X POST http://localhost:43451/hook -H 'Content-Type: application/json' -d @- 2>/dev/null || true","async":true}]}],
28
- "Stop": [{"hooks":[{"type":"command","command":"curl -sf -X POST http://localhost:43451/hook -H 'Content-Type: application/json' -d @- 2>/dev/null || true","async":true}]}],
29
- "Notification": [{"hooks":[{"type":"command","command":"curl -sf -X POST http://localhost:43451/hook -H 'Content-Type: application/json' -d @- 2>/dev/null || true","async":true}]}],
30
- "PermissionRequest": [{"hooks":[{"type":"command","command":"curl -sf -X POST http://localhost:43451/hook -H 'Content-Type: application/json' -d @- 2>/dev/null || true","async":true}]}]
31
- }
32
- }
33
- ```
34
-
35
- Open `http://localhost:43451` and start a Claude Code session.
36
-
37
- ## What You See
38
-
39
- - **File nodes** orbit their session's star at fixed radii — touched files grow slightly with each interaction
40
- - **Directional lasers**: Read/Grep/Glob fire planet→core (inbound scan), Edit/Write/Bash fire core→planet (outbound write)
41
- - **8 distinct effects**: reticle (Read), radar (Grep), dots (Glob), ink (Edit), burst (Write), lightning (Bash), wave (WebFetch), rings (Notification)
42
- - **Amber core + tether line** = agent/subagent session spawned from a parent
43
- - **Spinning amber ring** on core = session awaiting permission / user input
44
- - **Multiple clusters** = parallel Claude Code sessions, spaced dynamically
45
-
46
- ## Dev Mode
47
-
48
- ```bash
49
- git clone git@github.com:marisancans/claude-live.git
50
- cd claude-live
51
- npm install
52
- npm run dev
53
- ```
54
-
55
- Client: `http://localhost:5173` — Server: `http://localhost:43451`
56
-
57
- ## Requirements
58
-
59
- - Node.js 18+
60
- - `curl`
@@ -1,63 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Check if plugin version has changed and restart server if needed
5
- * Called on SessionStart to ensure server version matches plugin version
6
- */
7
-
8
- import { readFileSync, writeFileSync, mkdirSync } from 'fs';
9
- import { dirname, join } from 'path';
10
- import { fileURLToPath, pathToFileURL } from 'url';
11
- import { execSync } from 'child_process';
12
- import { homedir } from 'os';
13
-
14
- const __dirname = dirname(fileURLToPath(import.meta.url));
15
- const pluginRoot = dirname(__dirname);
16
- const versionFile = join(homedir(), '.claude', 'claude-live-version.txt');
17
-
18
- try {
19
- // Read current plugin version
20
- const packageJsonPath = join(pluginRoot, 'package.json');
21
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
22
- const currentVersion = packageJson.version;
23
-
24
- // Read last known version
25
- let lastVersion = '';
26
- try {
27
- lastVersion = readFileSync(versionFile, 'utf8').trim();
28
- } catch {
29
- // File doesn't exist yet, that's ok
30
- }
31
-
32
- // If versions differ, restart server
33
- if (lastVersion && lastVersion !== currentVersion) {
34
- console.log(`[claude-live] Plugin updated: ${lastVersion} → ${currentVersion}`);
35
- console.log('[claude-live] Restarting server...');
36
-
37
- // Kill any existing claude-live processes
38
- try {
39
- execSync('pkill -f "node.*claude-live" || true', { stdio: 'ignore' });
40
- // Give it a moment to die
41
- await new Promise(r => setTimeout(r, 500));
42
- } catch {
43
- // Process might not exist
44
- }
45
- }
46
-
47
- // Save current version
48
- mkdirSync(dirname(versionFile), { recursive: true });
49
- writeFileSync(versionFile, currentVersion);
50
-
51
- // Start server if not running
52
- const serverUrl = process.env.CLAUDE_LIVE_URL || 'http://localhost:43451';
53
- try {
54
- execSync(`curl -sf ${serverUrl}/buffer >/dev/null 2>&1`, { stdio: 'ignore' });
55
- console.log('[claude-live] Server already running');
56
- } catch {
57
- console.log('[claude-live] Starting server...');
58
- execSync(`npx claude-live@${currentVersion} >/tmp/claude-live.log 2>&1 &`, { stdio: 'ignore' });
59
- }
60
- } catch (error) {
61
- console.error('[claude-live] Error:', error.message);
62
- process.exit(1);
63
- }
package/bin/send-hook.sh DELETED
@@ -1,34 +0,0 @@
1
- #!/bin/sh
2
- # claude-live hook forwarder — reads URL from config with precedence:
3
- # 1. CLAUDE_LIVE_URL env var (override)
4
- # 2. .claude/claude-live.json (project)
5
- # 3. ~/.config/claude-live/config.json (global)
6
- # 4. http://localhost:43451 (default)
7
-
8
- URL=""
9
-
10
- # Debug: log that hook was called
11
- echo "[claude-live-hook] hook called" >> /tmp/claude-live-hook.log 2>&1
12
-
13
- # Project-level config
14
- if [ -f ".claude/claude-live.json" ]; then
15
- URL=$(cat .claude/claude-live.json 2>/dev/null | grep -o '"url" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"//')
16
- fi
17
-
18
- # Global config fallback
19
- if [ -z "$URL" ] && [ -f "$HOME/.config/claude-live/config.json" ]; then
20
- URL=$(cat "$HOME/.config/claude-live/config.json" 2>/dev/null | grep -o '"url" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"//')
21
- fi
22
-
23
- # Env var override
24
- if [ -n "$CLAUDE_LIVE_URL" ]; then
25
- URL="$CLAUDE_LIVE_URL"
26
- fi
27
-
28
- # Default
29
- URL="${URL:-http://localhost:43451}"
30
-
31
- # Debug: log what URL we're using and what we're sending
32
- echo "[claude-live-hook] sending to $URL" >> /tmp/claude-live-hook.log 2>&1
33
-
34
- curl -sf -X POST "$URL/hook" -H 'Content-Type: application/json' -d @- 2>/tmp/claude-live-hook-error.log || true
@@ -1,33 +0,0 @@
1
- #!/bin/sh
2
- # claude-live server launcher — reads URL from config with precedence:
3
- # 1. CLAUDE_LIVE_URL env var (override)
4
- # 2. .claude/claude-live.json (project)
5
- # 3. ~/.config/claude-live/config.json (global)
6
- # 4. http://localhost:43451 (default)
7
-
8
- URL=""
9
-
10
- # Project-level config
11
- if [ -f ".claude/claude-live.json" ]; then
12
- URL=$(cat .claude/claude-live.json 2>/dev/null | grep -o '"url" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"//')
13
- fi
14
-
15
- # Global config fallback
16
- if [ -z "$URL" ] && [ -f "$HOME/.config/claude-live/config.json" ]; then
17
- URL=$(cat "$HOME/.config/claude-live/config.json" 2>/dev/null | grep -o '"url" *: *"[^"]*"' | head -1 | sed 's/.*: *"//;s/"//')
18
- fi
19
-
20
- # Env var override
21
- if [ -n "$CLAUDE_LIVE_URL" ]; then
22
- URL="$CLAUDE_LIVE_URL"
23
- fi
24
-
25
- # Default
26
- URL="${URL:-http://localhost:43451}"
27
-
28
- # Only auto-start server if pointing to localhost
29
- case "$URL" in
30
- http://localhost:*|http://127.0.0.1:*)
31
- curl -sf "$URL/buffer" >/dev/null 2>&1 || (npx claude-live@latest >/tmp/claude-live.log 2>&1 &)
32
- ;;
33
- esac