claude-session-viewer 0.1.1 → 0.2.0
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 +45 -10
- package/bin/cli.js +35 -4
- package/bin/dev.js +18 -5
- package/dist/client/assets/index-BloGA6Iu.js +51 -0
- package/dist/client/assets/index-Dg6fR2pp.css +1 -0
- package/dist/client/index.html +2 -2
- package/dist/server/index.js +46 -7
- package/package.json +10 -8
- package/dist/client/assets/index-BRGpp7Nq.js +0 -40
- package/dist/client/assets/index-bRG2avxz.css +0 -1
package/README.md
CHANGED
|
@@ -1,38 +1,73 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
</div>
|
|
6
|
+
|
|
1
7
|
# Claude Session Viewer
|
|
2
8
|
|
|
3
9
|
A web-based tool to visualize Claude session history from your local `.claude` directory in a timeline format.
|
|
4
10
|
|
|
5
11
|
## Getting Started
|
|
6
12
|
|
|
7
|
-
###
|
|
13
|
+
### Run with npx
|
|
8
14
|
|
|
9
15
|
```bash
|
|
10
|
-
|
|
16
|
+
npx claude-session-viewer
|
|
11
17
|
```
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
The server will start and automatically open in your default web browser. By default, it uses port 9090, but if that port is unavailable, it will automatically find an available port.
|
|
20
|
+
|
|
21
|
+
You'll see output like this in your terminal:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Server running on http://localhost:9090
|
|
25
|
+
Watching Claude directory: /Users/username/.claude
|
|
26
|
+
|
|
27
|
+
Opening browser at http://localhost:9090...
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Options
|
|
31
|
+
|
|
32
|
+
You can specify a custom port using the `--port` or `-p` option:
|
|
14
33
|
|
|
15
34
|
```bash
|
|
16
|
-
npx
|
|
35
|
+
npx claude-session-viewer --port 3000
|
|
17
36
|
```
|
|
18
37
|
|
|
19
|
-
|
|
38
|
+
When you specify a port, the server will fail if that port is already in use. If you don't specify a port and the default (9090) is unavailable, it will automatically find an available port.
|
|
39
|
+
|
|
40
|
+
### Development
|
|
41
|
+
|
|
42
|
+
If you want to modify the source code or run in development mode, first install dependencies:
|
|
20
43
|
|
|
21
44
|
```bash
|
|
22
|
-
|
|
45
|
+
npm install
|
|
23
46
|
```
|
|
24
47
|
|
|
25
|
-
|
|
48
|
+
Then run the development server:
|
|
26
49
|
|
|
27
50
|
```bash
|
|
28
51
|
npm run dev
|
|
29
52
|
```
|
|
30
53
|
|
|
31
54
|
This command runs both:
|
|
32
|
-
- Backend server (http://localhost:
|
|
33
|
-
- Frontend development server (http://localhost:5173)
|
|
55
|
+
- Backend server (default: http://localhost:9090)
|
|
56
|
+
- Frontend development server (default: http://localhost:5173)
|
|
34
57
|
|
|
35
|
-
|
|
58
|
+
The application will automatically open in your default web browser. By default, it uses ports 9090 (backend) and 5173 (frontend), but if those ports are unavailable, it will automatically find available ports.
|
|
59
|
+
|
|
60
|
+
You'll see output like this in your terminal:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
VITE v5.4.21 ready in 149 ms
|
|
64
|
+
➜ Local: http://localhost:5173/
|
|
65
|
+
|
|
66
|
+
Server running on http://localhost:9090
|
|
67
|
+
Watching Claude directory: /Users/username/.claude
|
|
68
|
+
|
|
69
|
+
Opening browser at http://localhost:5173...
|
|
70
|
+
```
|
|
36
71
|
|
|
37
72
|
### Build
|
|
38
73
|
|
package/bin/cli.js
CHANGED
|
@@ -3,6 +3,10 @@ import { spawn } from "node:child_process";
|
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import open from "open";
|
|
7
|
+
import getPort from "get-port";
|
|
8
|
+
|
|
9
|
+
const DEFAULT_PORT = 9090;
|
|
6
10
|
|
|
7
11
|
const args = process.argv.slice(2);
|
|
8
12
|
|
|
@@ -12,11 +16,12 @@ if (args.includes("--help") || args.includes("-h")) {
|
|
|
12
16
|
"Claude Session Viewer",
|
|
13
17
|
"",
|
|
14
18
|
"Usage:",
|
|
15
|
-
" npx claude-session-viewer",
|
|
19
|
+
" npx claude-session-viewer [options]",
|
|
16
20
|
"",
|
|
17
21
|
"Options:",
|
|
18
|
-
" -
|
|
19
|
-
" -
|
|
22
|
+
" -p, --port <port> Specify port number (default: 9090)",
|
|
23
|
+
" -h, --help Show this help message",
|
|
24
|
+
" -v, --version Show package version",
|
|
20
25
|
"",
|
|
21
26
|
].join("\n"),
|
|
22
27
|
);
|
|
@@ -29,6 +34,19 @@ if (args.includes("--version") || args.includes("-v")) {
|
|
|
29
34
|
process.exit(0);
|
|
30
35
|
}
|
|
31
36
|
|
|
37
|
+
// Handle port option
|
|
38
|
+
let port = 0;
|
|
39
|
+
const portIndex = args.findIndex((arg) => arg === "--port" || arg === "-p");
|
|
40
|
+
if (portIndex !== -1 && args[portIndex + 1]) {
|
|
41
|
+
const userPort = Number(args[portIndex + 1]);
|
|
42
|
+
if (Number.isFinite(userPort) && userPort > 0 && userPort < 65536) {
|
|
43
|
+
port = userPort;
|
|
44
|
+
} else {
|
|
45
|
+
console.error(`Invalid port number: ${args[portIndex + 1]}`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
32
50
|
const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
33
51
|
const serverEntry = resolve(rootDir, "dist/server/index.js");
|
|
34
52
|
|
|
@@ -38,11 +56,24 @@ if (!existsSync(serverEntry)) {
|
|
|
38
56
|
process.exit(1);
|
|
39
57
|
}
|
|
40
58
|
|
|
59
|
+
// Only use getPort if port was not specified (port === 0)
|
|
60
|
+
if (port === 0) {
|
|
61
|
+
port = await getPort({ port: DEFAULT_PORT });
|
|
62
|
+
}
|
|
63
|
+
|
|
41
64
|
const child = spawn(process.execPath, [serverEntry], {
|
|
42
65
|
cwd: rootDir,
|
|
43
66
|
stdio: "inherit",
|
|
67
|
+
env: { ...process.env, PORT: String(port) },
|
|
44
68
|
});
|
|
45
69
|
|
|
70
|
+
// Wait for server to start, then open browser
|
|
71
|
+
setTimeout(async () => {
|
|
72
|
+
const url = `http://localhost:${port}`;
|
|
73
|
+
console.log(`\nOpening browser at ${url}...`);
|
|
74
|
+
await open(url);
|
|
75
|
+
}, 1000);
|
|
76
|
+
|
|
46
77
|
child.on("exit", (code) => {
|
|
47
78
|
if (code !== null) {
|
|
48
79
|
process.exit(code);
|
|
@@ -50,6 +81,6 @@ child.on("exit", (code) => {
|
|
|
50
81
|
});
|
|
51
82
|
|
|
52
83
|
child.on("error", (error) => {
|
|
53
|
-
console.error("Failed to start
|
|
84
|
+
console.error("Failed to start server:", error.message);
|
|
54
85
|
process.exit(1);
|
|
55
86
|
});
|
package/bin/dev.js
CHANGED
|
@@ -3,12 +3,15 @@ import { spawn } from "node:child_process";
|
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import getPort from "get-port";
|
|
6
|
+
import open from "open";
|
|
7
|
+
|
|
8
|
+
const DEFAULT_SERVER_PORT = 9090;
|
|
9
|
+
const DEFAULT_CLIENT_PORT = 5173;
|
|
6
10
|
|
|
7
11
|
const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
8
12
|
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const port = await getPort({ port: DEFAULT_PORT });
|
|
13
|
+
const serverPort = await getPort({ port: DEFAULT_SERVER_PORT });
|
|
14
|
+
const clientPort = await getPort({ port: DEFAULT_CLIENT_PORT });
|
|
12
15
|
|
|
13
16
|
const children = new Set();
|
|
14
17
|
|
|
@@ -25,8 +28,18 @@ function spawnProcess(args, envOverrides) {
|
|
|
25
28
|
return child;
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
spawnProcess(["run", "dev:server"], { PORT: String(
|
|
29
|
-
spawnProcess(["run", "dev:client"], {
|
|
31
|
+
spawnProcess(["run", "dev:server"], { PORT: String(serverPort) });
|
|
32
|
+
spawnProcess(["run", "dev:client"], {
|
|
33
|
+
VITE_SERVER_PORT: String(serverPort),
|
|
34
|
+
VITE_CLIENT_PORT: String(clientPort),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Wait for Vite to start, then open browser
|
|
38
|
+
setTimeout(async () => {
|
|
39
|
+
const url = `http://localhost:${clientPort}`;
|
|
40
|
+
console.log(`\nOpening browser at ${url}...`);
|
|
41
|
+
await open(url);
|
|
42
|
+
}, 1000);
|
|
30
43
|
|
|
31
44
|
function shutdown(signal) {
|
|
32
45
|
for (const child of children) {
|