seeclaudecode 1.0.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.
@@ -0,0 +1,27 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ publish:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ id-token: write
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: '20'
21
+ registry-url: 'https://registry.npmjs.org'
22
+
23
+ - run: npm install
24
+
25
+ - run: npm publish --access public
26
+ env:
27
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # SeeClaudeCode
2
+
3
+ Real-time visualization of your repository structure while Claude Code edits your codebase.
4
+
5
+ ## Features
6
+
7
+ - **Architecture Graph** - Interactive diagram showing your project's directory structure with pan/zoom
8
+ - **Sunburst View** - Radial visualization of your codebase hierarchy
9
+ - **File Explorer** - Traditional tree view with change tracking
10
+ - **Real-time Git Diff** - See exactly what changed in any file or directory
11
+ - **Live Highlighting**:
12
+ - **Yellow pulse** - Files with pending changes (git diff)
13
+ - **Green pulse** - Files currently being edited
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install -g seeclaudecode
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ # Interactive mode - prompts for directory selection
25
+ seeclaudecode
26
+
27
+ # Monitor specific directory
28
+ seeclaudecode ./my-project
29
+
30
+ # Monitor with absolute path
31
+ seeclaudecode /path/to/repo
32
+
33
+ # Use custom port
34
+ seeclaudecode . --port 4000
35
+
36
+ # Don't auto-open browser
37
+ seeclaudecode . --no-open
38
+ ```
39
+
40
+ When started without a directory argument, you'll see an interactive menu:
41
+ ```
42
+ Select a directory to monitor:
43
+
44
+ 1) Current directory
45
+ /Users/you/projects
46
+ 2) my-app
47
+ /Users/you/projects/my-app
48
+
49
+ Or enter a custom path
50
+
51
+ 📁 Directory:
52
+ ```
53
+
54
+ ## Switching Directories
55
+
56
+ While running, you can switch to a different directory at any time:
57
+ - Type a new path and press Enter to switch
58
+ - Type `quit` or `exit` to stop
59
+
60
+ ## Options
61
+
62
+ | Option | Description |
63
+ |--------|-------------|
64
+ | `-p, --port <port>` | Port to run server on (default: 3847) |
65
+ | `-n, --no-open` | Don't automatically open browser |
66
+ | `-h, --help` | Show help message |
67
+ | `-v, --version` | Show version number |
68
+
69
+ ## How It Works
70
+
71
+ 1. Start SeeClaudeCode (it will prompt for a directory or use the one you specify)
72
+ 2. Open the displayed URL in your browser
73
+ 3. Run Claude Code in the same directory
74
+ 4. Watch as files pulse and highlight when Claude makes changes
75
+ 5. Click on any file or directory to see the git diff
76
+ 6. Switch directories anytime by typing a new path
77
+
78
+ ## Views
79
+
80
+ ### Architecture Graph
81
+ An interactive node-based diagram showing your project structure. Changed files appear below their parent directories with pulsing yellow highlights.
82
+
83
+ ### Sunburst View
84
+ A radial visualization where each ring represents a directory level. Click on segments to see diffs for that directory.
85
+
86
+ ### File Explorer
87
+ A traditional tree view showing all files with color-coded change indicators.
88
+
89
+ ## Visual Indicators
90
+
91
+ | Indicator | Meaning |
92
+ |-----------|---------|
93
+ | Yellow pulsing | Pending changes (in git diff) |
94
+ | Green pulsing | Currently being edited |
95
+ | Purple nodes | Directories |
96
+ | Green nodes | Code files (.js, .ts, .py, etc.) |
97
+ | Pink nodes | Style files (.css, .scss) |
98
+ | Orange nodes | Config files (.json, .yaml) |
99
+ | Blue nodes | Documentation (.md, .txt) |
100
+
101
+ ## Requirements
102
+
103
+ - Node.js 18.0.0 or higher
104
+ - Git (for diff functionality)
105
+
106
+ ## Development
107
+
108
+ ```bash
109
+ # Clone and install
110
+ git clone <repo-url>
111
+ cd seeclaudecode
112
+ npm install
113
+
114
+ # Run locally
115
+ npm start /path/to/repo
116
+
117
+ # Link for global testing
118
+ npm link
119
+ seeclaudecode /path/to/repo
120
+ ```
121
+
122
+ ## Architecture
123
+
124
+ ```
125
+ seeclaudecode/
126
+ ├── bin/
127
+ │ └── cli.js # CLI entry point
128
+ ├── public/
129
+ │ ├── index.html # Main HTML structure
130
+ │ ├── styles.css # Styling and animations
131
+ │ └── app.js # Frontend visualization logic
132
+ ├── server.js # Express server with WebSocket & file watching
133
+ └── package.json
134
+ ```
135
+
136
+ ## License
137
+
138
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { fileURLToPath } from 'url';
4
+ import { dirname, join, resolve } from 'path';
5
+ import { existsSync, statSync, readdirSync } from 'fs';
6
+ import { spawn } from 'child_process';
7
+ import { createInterface } from 'readline';
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+
12
+ // Parse arguments
13
+ const args = process.argv.slice(2);
14
+ let targetDir = null; // Don't default to cwd - prompt instead
15
+ let port = 3847;
16
+ let openBrowser = true;
17
+
18
+ // Help text
19
+ const helpText = `
20
+ SeeClaudeCode - Watch Claude Code edit your codebase in real-time
21
+
22
+ Usage:
23
+ seeclaudecode [directory] [options]
24
+
25
+ Arguments:
26
+ directory Directory to monitor (will prompt if not provided)
27
+
28
+ Options:
29
+ -p, --port <port> Port to run server on (default: 3847)
30
+ -n, --no-open Don't automatically open browser
31
+ -h, --help Show this help message
32
+ -v, --version Show version number
33
+
34
+ Examples:
35
+ seeclaudecode # Prompts for directory
36
+ seeclaudecode ./my-project # Monitor specific directory
37
+ seeclaudecode /path/to/repo # Monitor absolute path
38
+ seeclaudecode . --port 4000 # Use custom port
39
+
40
+ While running:
41
+ Type a new path and press Enter to switch directories
42
+ Type 'quit' or 'exit' to stop
43
+
44
+ Once running, open the displayed URL in your browser to see:
45
+ - Architecture graph of your codebase
46
+ - Sunburst visualization
47
+ - File explorer with change tracking
48
+ - Real-time git diff viewer
49
+ - Yellow pulsing highlights for pending changes
50
+ - Green pulsing for files being actively edited
51
+ `;
52
+
53
+ // Parse arguments
54
+ for (let i = 0; i < args.length; i++) {
55
+ const arg = args[i];
56
+
57
+ if (arg === '-h' || arg === '--help') {
58
+ console.log(helpText);
59
+ process.exit(0);
60
+ }
61
+
62
+ if (arg === '-v' || arg === '--version') {
63
+ const pkg = await import('../package.json', { with: { type: 'json' } });
64
+ console.log(`seeclaudecode v${pkg.default.version}`);
65
+ process.exit(0);
66
+ }
67
+
68
+ if (arg === '-p' || arg === '--port') {
69
+ port = parseInt(args[++i], 10);
70
+ if (isNaN(port)) {
71
+ console.error('Error: Invalid port number');
72
+ process.exit(1);
73
+ }
74
+ continue;
75
+ }
76
+
77
+ if (arg === '-n' || arg === '--no-open') {
78
+ openBrowser = false;
79
+ continue;
80
+ }
81
+
82
+ if (!arg.startsWith('-')) {
83
+ targetDir = resolve(arg);
84
+ }
85
+ }
86
+
87
+ // Create readline interface
88
+ const rl = createInterface({
89
+ input: process.stdin,
90
+ output: process.stdout
91
+ });
92
+
93
+ // Promisified question
94
+ function question(prompt) {
95
+ return new Promise((resolve) => {
96
+ rl.question(prompt, resolve);
97
+ });
98
+ }
99
+
100
+ // Validate directory
101
+ function validateDirectory(dir) {
102
+ const resolved = resolve(dir);
103
+ if (!existsSync(resolved)) {
104
+ return { valid: false, error: `Directory does not exist: ${resolved}` };
105
+ }
106
+ if (!statSync(resolved).isDirectory()) {
107
+ return { valid: false, error: `Path is not a directory: ${resolved}` };
108
+ }
109
+ return { valid: true, path: resolved };
110
+ }
111
+
112
+ // Get suggested directories (recent git repos, common project locations)
113
+ function getSuggestedDirs() {
114
+ const suggestions = [];
115
+ const cwd = process.cwd();
116
+
117
+ // Add current directory
118
+ suggestions.push({ path: cwd, label: 'Current directory' });
119
+
120
+ // Check for subdirectories that look like projects
121
+ try {
122
+ const entries = readdirSync(cwd, { withFileTypes: true });
123
+ for (const entry of entries) {
124
+ if (entry.isDirectory() && !entry.name.startsWith('.') && !entry.name.startsWith('node_modules')) {
125
+ const subPath = join(cwd, entry.name);
126
+ // Check if it's a git repo or has package.json
127
+ if (existsSync(join(subPath, '.git')) || existsSync(join(subPath, 'package.json'))) {
128
+ suggestions.push({ path: subPath, label: entry.name });
129
+ }
130
+ }
131
+ }
132
+ } catch (e) {
133
+ // Ignore errors
134
+ }
135
+
136
+ return suggestions.slice(0, 5); // Max 5 suggestions
137
+ }
138
+
139
+ // Print banner
140
+ function printBanner() {
141
+ console.log(`
142
+ \x1b[36m╔═══════════════════════════════════════════════════════════╗
143
+ ║ ║
144
+ ║ \x1b[33m👁️ SeeClaudeCode\x1b[36m ║
145
+ ║ \x1b[90mWatch Claude Code edit your codebase in real-time\x1b[36m ║
146
+ ║ ║
147
+ ╚═══════════════════════════════════════════════════════════╝\x1b[0m
148
+ `);
149
+ }
150
+
151
+ // Prompt for directory
152
+ async function promptForDirectory() {
153
+ const suggestions = getSuggestedDirs();
154
+
155
+ console.log('\x1b[36mSelect a directory to monitor:\x1b[0m\n');
156
+
157
+ suggestions.forEach((s, i) => {
158
+ console.log(` \x1b[33m${i + 1})\x1b[0m ${s.label}`);
159
+ if (s.label !== s.path) {
160
+ console.log(` \x1b[90m${s.path}\x1b[0m`);
161
+ }
162
+ });
163
+
164
+ console.log(`\n \x1b[90mOr enter a custom path\x1b[0m\n`);
165
+
166
+ while (true) {
167
+ const answer = await question('\x1b[36m📁 Directory:\x1b[0m ');
168
+
169
+ // Check if it's a number selection
170
+ const num = parseInt(answer, 10);
171
+ if (!isNaN(num) && num >= 1 && num <= suggestions.length) {
172
+ return suggestions[num - 1].path;
173
+ }
174
+
175
+ // Treat as a path
176
+ if (answer.trim()) {
177
+ const result = validateDirectory(answer.trim());
178
+ if (result.valid) {
179
+ return result.path;
180
+ }
181
+ console.log(`\x1b[31m${result.error}\x1b[0m`);
182
+ }
183
+ }
184
+ }
185
+
186
+ // Server management
187
+ let server = null;
188
+ let currentDir = null;
189
+
190
+ function startServer(dir) {
191
+ currentDir = dir;
192
+
193
+ console.log(`\n\x1b[90m📁 Monitoring:\x1b[0m ${dir}`);
194
+ console.log(`\x1b[90m🌐 Server:\x1b[0m http://localhost:${port}`);
195
+ console.log(`\n\x1b[90m💡 Type a new path to switch directories, or 'quit' to exit\x1b[0m\n`);
196
+
197
+ const serverPath = join(__dirname, '..', 'server.js');
198
+ server = spawn('node', [serverPath, dir], {
199
+ stdio: ['pipe', 'inherit', 'inherit'],
200
+ env: { ...process.env, PORT: port.toString() }
201
+ });
202
+
203
+ server.on('close', (code) => {
204
+ if (code !== null && code !== 0) {
205
+ console.error(`\x1b[31mServer exited with code ${code}\x1b[0m`);
206
+ }
207
+ });
208
+
209
+ return server;
210
+ }
211
+
212
+ function stopServer() {
213
+ if (server) {
214
+ server.kill('SIGTERM');
215
+ server = null;
216
+ }
217
+ }
218
+
219
+ function restartServer(newDir) {
220
+ console.log(`\n\x1b[33m🔄 Switching to: ${newDir}\x1b[0m`);
221
+ stopServer();
222
+
223
+ // Brief delay before restarting
224
+ setTimeout(() => {
225
+ startServer(newDir);
226
+ }, 500);
227
+ }
228
+
229
+ // Main
230
+ async function main() {
231
+ printBanner();
232
+
233
+ // If directory wasn't provided as argument, prompt for it
234
+ if (!targetDir) {
235
+ targetDir = await promptForDirectory();
236
+ } else {
237
+ // Validate provided directory
238
+ const result = validateDirectory(targetDir);
239
+ if (!result.valid) {
240
+ console.error(`\x1b[31mError: ${result.error}\x1b[0m`);
241
+ process.exit(1);
242
+ }
243
+ targetDir = result.path;
244
+ }
245
+
246
+ // Start the server
247
+ startServer(targetDir);
248
+
249
+ // Open browser after a short delay
250
+ if (openBrowser) {
251
+ setTimeout(async () => {
252
+ try {
253
+ const open = (await import('open')).default;
254
+ await open(`http://localhost:${port}`);
255
+ } catch (e) {
256
+ // Silently fail if can't open browser
257
+ }
258
+ }, 1500);
259
+ }
260
+
261
+ // Listen for directory changes
262
+ rl.on('line', (input) => {
263
+ const trimmed = input.trim();
264
+
265
+ if (trimmed === 'quit' || trimmed === 'exit') {
266
+ console.log('\n\x1b[90mShutting down...\x1b[0m');
267
+ stopServer();
268
+ rl.close();
269
+ process.exit(0);
270
+ }
271
+
272
+ if (trimmed) {
273
+ const result = validateDirectory(trimmed);
274
+ if (result.valid) {
275
+ restartServer(result.path);
276
+ } else {
277
+ console.log(`\x1b[31m${result.error}\x1b[0m`);
278
+ }
279
+ }
280
+ });
281
+
282
+ // Handle exit
283
+ process.on('SIGINT', () => {
284
+ console.log('\n\x1b[90mShutting down...\x1b[0m');
285
+ stopServer();
286
+ rl.close();
287
+ process.exit(0);
288
+ });
289
+
290
+ process.on('SIGTERM', () => {
291
+ stopServer();
292
+ rl.close();
293
+ process.exit(0);
294
+ });
295
+ }
296
+
297
+ main().catch((err) => {
298
+ console.error(err);
299
+ process.exit(1);
300
+ });
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "seeclaudecode",
3
+ "version": "1.0.0",
4
+ "description": "Real-time visualization of repository structure - watch Claude Code edit your codebase",
5
+ "main": "server.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "seeclaudecode": "./bin/cli.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node server.js",
12
+ "dev": "node server.js"
13
+ },
14
+ "dependencies": {
15
+ "chokidar": "^3.5.3",
16
+ "express": "^4.18.2",
17
+ "open": "^10.0.0",
18
+ "simple-git": "^3.22.0",
19
+ "ws": "^8.16.0"
20
+ },
21
+ "keywords": [
22
+ "visualization",
23
+ "repository",
24
+ "claude-code",
25
+ "claude",
26
+ "developer-tools",
27
+ "git",
28
+ "diff",
29
+ "real-time"
30
+ ],
31
+ "author": "",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": ""
36
+ },
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ }
40
+ }