@eyeglass/cli 0.1.4 → 0.1.5

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 (3) hide show
  1. package/README.md +28 -7
  2. package/dist/index.js +284 -24
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -8,20 +8,38 @@ CLI for initializing [Eyeglass](https://github.com/donutboyband/eyeglass) in you
8
8
  npx @eyeglass/cli init
9
9
  ```
10
10
 
11
- This single command will:
12
-
13
- 1. **Install** `@eyeglass/inspector` as a dev dependency
14
- 2. **Create** `.claude/settings.json` with MCP server configuration
15
- 3. **Configure** your bundler (Vite, Next.js, CRA, or Remix)
11
+ This will interactively prompt you to select which AI coding agents to configure:
12
+ - **Claude Code** - stdio MCP (`.claude/settings.json`)
13
+ - **GitHub Copilot CLI** - local MCP (`.copilot/mcp-config.json`)
14
+ - **OpenAI Codex CLI** - HTTP API (`.codex/eyeglass.md`)
16
15
 
17
16
  ## Options
18
17
 
19
18
  ```bash
19
+ # Interactive setup (prompts for agent selection)
20
+ npx @eyeglass/cli init
21
+
22
+ # Configure specific agents
23
+ npx @eyeglass/cli init --claude # Claude Code only
24
+ npx @eyeglass/cli init --copilot # GitHub Copilot CLI only
25
+ npx @eyeglass/cli init --codex # OpenAI Codex only
26
+ npx @eyeglass/cli init --claude --copilot # Multiple agents
27
+
28
+ # Other options
20
29
  npx @eyeglass/cli init --dry-run # Preview changes without making them
21
30
  npx @eyeglass/cli init --skip-install # Skip installing @eyeglass/inspector
22
31
  npx @eyeglass/cli help # Show help
23
32
  ```
24
33
 
34
+ ## What It Does
35
+
36
+ 1. **Installs** `@eyeglass/inspector` as a dev dependency
37
+ 2. **Creates** agent-specific config files:
38
+ - Claude: `.claude/settings.json` + `.claude/skills/eyeglass.md`
39
+ - Copilot CLI: `.copilot/mcp-config.json`
40
+ - Codex: `.codex/eyeglass.md` (HTTP API instructions)
41
+ 3. **Configures** your bundler (Vite, Next.js, CRA, or Remix)
42
+
25
43
  ## Supported Frameworks
26
44
 
27
45
  | Framework | Auto-Detection | Component Names | File Paths |
@@ -34,8 +52,11 @@ npx @eyeglass/cli help # Show help
34
52
  ## After Setup
35
53
 
36
54
  1. Start your dev server (`npm run dev`)
37
- 2. Run `claude` in your project directory
38
- 3. Tell Claude: `watch eyeglass` or `eg`
55
+ 2. Start the Eyeglass bridge: `npx eyeglass-bridge`
56
+ 3. Start your AI coding agent:
57
+ - **Claude Code**: Run `claude` and say "watch eyeglass" or "/eyeglass"
58
+ - **Copilot CLI**: Run `gh copilot` in your project directory
59
+ - **Codex**: See `.codex/eyeglass.md` for HTTP API usage
39
60
  4. Select elements in your browser and submit requests!
40
61
 
41
62
  See the [main repo](https://github.com/donutboyband/eyeglass) for full documentation.
package/dist/index.js CHANGED
@@ -1,10 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
+ import * as readline from 'readline';
4
5
  import { execFileSync } from 'child_process';
5
6
  // ============================================================================
6
7
  // Templates
7
8
  // ============================================================================
9
+ // ASCII art logo based on eyeglass.svg - glasses with cursor pointer in right lens
10
+ // SVG has: two round lenses, short vertical bridge, temples angling up-outward, pointer in right lens
11
+ const LOGO = `
12
+ \x1b[36m ╱ ╲
13
+ ╲ ╭───────╮ ╭───────╮ ╱
14
+ │ │ │ \x1b[34m▲\x1b[36m │
15
+ │ │ │ │ \x1b[34m█▸\x1b[36m │
16
+ ╰───────╯ ╰───────╯\x1b[0m
17
+ \x1b[1meyeglass\x1b[0m
18
+ `;
8
19
  const NEXT_CONFIG_ADDITION = `
9
20
  // Eyeglass configuration - Auto-generated by eyeglass init
10
21
  const withEyeglass = (nextConfig) => {
@@ -26,14 +37,28 @@ const withEyeglass = (nextConfig) => {
26
37
  };
27
38
  };
28
39
  `;
40
+ const MCP_STDIO_CONFIG = {
41
+ command: 'npx',
42
+ args: ['eyeglass-bridge'],
43
+ };
29
44
  const CLAUDE_CONFIG = {
45
+ mcpServers: {
46
+ eyeglass: MCP_STDIO_CONFIG,
47
+ },
48
+ };
49
+ // GitHub Copilot CLI agent config format (.copilot/mcp-config.json)
50
+ const COPILOT_MCP_CONFIG = {
30
51
  mcpServers: {
31
52
  eyeglass: {
53
+ type: 'local',
32
54
  command: 'npx',
33
55
  args: ['eyeglass-bridge'],
56
+ tools: ['*'],
34
57
  },
35
58
  },
36
59
  };
60
+ // Codex CLI uses HTTP endpoints, so we just provide instructions
61
+ const CODEX_BASE_URL = 'http://localhost:3300/api';
37
62
  const EYEGLASS_SKILL = `---
38
63
  name: eyeglass
39
64
  description: Listen for Eyeglass requests from the browser and make UI changes
@@ -120,6 +145,48 @@ function readFile(filePath) {
120
145
  function writeFile(filePath, content) {
121
146
  fs.writeFileSync(filePath, content, 'utf-8');
122
147
  }
148
+ async function promptAgentSelection() {
149
+ const agents = [
150
+ { key: '1', name: 'Claude Code', type: 'claude', selected: false },
151
+ { key: '2', name: 'GitHub Copilot CLI', type: 'copilot', selected: false },
152
+ { key: '3', name: 'OpenAI Codex CLI', type: 'codex', selected: false },
153
+ ];
154
+ const rl = readline.createInterface({
155
+ input: process.stdin,
156
+ output: process.stdout,
157
+ });
158
+ const question = (prompt) => {
159
+ return new Promise((resolve) => {
160
+ rl.question(prompt, resolve);
161
+ });
162
+ };
163
+ console.log('\n\x1b[1mSelect coding agents to configure:\x1b[0m');
164
+ console.log('\x1b[2m(Enter numbers separated by spaces, or "a" for all)\x1b[0m\n');
165
+ for (const agent of agents) {
166
+ console.log(` ${agent.key}) ${agent.name}`);
167
+ }
168
+ console.log('');
169
+ const answer = await question('\x1b[36m>\x1b[0m ');
170
+ rl.close();
171
+ const input = answer.trim().toLowerCase();
172
+ if (input === 'a' || input === 'all') {
173
+ return agents.map((a) => a.type);
174
+ }
175
+ const selected = [];
176
+ const parts = input.split(/[\s,]+/);
177
+ for (const part of parts) {
178
+ const agent = agents.find((a) => a.key === part);
179
+ if (agent && !selected.includes(agent.type)) {
180
+ selected.push(agent.type);
181
+ }
182
+ }
183
+ // Default to Claude if nothing selected
184
+ if (selected.length === 0) {
185
+ log('No selection made, defaulting to Claude Code', 'warn');
186
+ return ['claude'];
187
+ }
188
+ return selected;
189
+ }
123
190
  function detectPackageManager() {
124
191
  const cwd = process.cwd();
125
192
  if (fileExists(path.join(cwd, 'bun.lockb')))
@@ -268,6 +335,132 @@ function setupClaudeConfig(dryRun) {
268
335
  }
269
336
  return true;
270
337
  }
338
+ function setupCopilotConfig(dryRun) {
339
+ const cwd = process.cwd();
340
+ const copilotDir = path.join(cwd, '.copilot');
341
+ const configPath = path.join(copilotDir, 'mcp-config.json');
342
+ if (fileExists(configPath)) {
343
+ try {
344
+ const existing = JSON.parse(readFile(configPath));
345
+ if (existing.mcpServers?.eyeglass) {
346
+ log('Copilot CLI MCP config already exists', 'success');
347
+ return true;
348
+ }
349
+ // Merge with existing config
350
+ const merged = {
351
+ ...existing,
352
+ mcpServers: {
353
+ ...existing.mcpServers,
354
+ ...COPILOT_MCP_CONFIG.mcpServers,
355
+ },
356
+ };
357
+ if (dryRun) {
358
+ log('Would update .copilot/mcp-config.json with eyeglass MCP config');
359
+ }
360
+ else {
361
+ writeFile(configPath, JSON.stringify(merged, null, 2));
362
+ log('Added eyeglass to existing Copilot CLI MCP config', 'success');
363
+ }
364
+ return true;
365
+ }
366
+ catch {
367
+ log('Could not parse existing .copilot/mcp-config.json', 'warn');
368
+ return false;
369
+ }
370
+ }
371
+ if (dryRun) {
372
+ log(`Would create ${configPath}`);
373
+ }
374
+ else {
375
+ if (!fileExists(copilotDir)) {
376
+ fs.mkdirSync(copilotDir, { recursive: true });
377
+ }
378
+ writeFile(configPath, JSON.stringify(COPILOT_MCP_CONFIG, null, 2));
379
+ log('Created .copilot/mcp-config.json for GitHub Copilot CLI', 'success');
380
+ }
381
+ return true;
382
+ }
383
+ function setupCodexConfig(dryRun) {
384
+ const cwd = process.cwd();
385
+ const codexDir = path.join(cwd, '.codex');
386
+ const configPath = path.join(codexDir, 'eyeglass.md');
387
+ const codexInstructions = `# Eyeglass Integration for Codex CLI
388
+
389
+ Eyeglass provides HTTP endpoints for interacting with UI elements selected in the browser.
390
+
391
+ ## Base URL
392
+ \`${CODEX_BASE_URL}\`
393
+
394
+ ## Endpoints
395
+
396
+ ### Wait for Request (blocking)
397
+ \`\`\`
398
+ GET /api/wait?timeout=300000
399
+ \`\`\`
400
+ Blocks until user selects an element. Returns markdown with element context.
401
+
402
+ ### Get Current Focus
403
+ \`\`\`
404
+ GET /api/focus
405
+ \`\`\`
406
+ Returns the currently focused element as markdown.
407
+
408
+ ### Update Status
409
+ \`\`\`
410
+ POST /api/status
411
+ Content-Type: application/json
412
+
413
+ {"status": "fixing", "message": "Working on it..."}
414
+ \`\`\`
415
+ Status values: \`idle\`, \`pending\`, \`fixing\`, \`success\`, \`failed\`
416
+
417
+ ### Report Action
418
+ \`\`\`
419
+ POST /api/action
420
+ Content-Type: application/json
421
+
422
+ {"action": "reading", "target": "src/components/Button.tsx"}
423
+ \`\`\`
424
+ Actions: \`reading\`, \`writing\`, \`searching\`, \`thinking\`
425
+
426
+ ### Send Thought
427
+ \`\`\`
428
+ POST /api/thought
429
+ Content-Type: application/json
430
+
431
+ {"content": "I think we should use a CSS variable for this color..."}
432
+ \`\`\`
433
+
434
+ ### Get History
435
+ \`\`\`
436
+ GET /api/history
437
+ \`\`\`
438
+ Returns up to 5 previous focus requests.
439
+
440
+ ## Workflow
441
+
442
+ 1. Start the bridge: \`npx eyeglass-bridge\`
443
+ 2. Call \`GET /api/wait\` to block until user selects an element
444
+ 3. Make your changes based on the returned context
445
+ 4. Call \`POST /api/status\` with \`{"status": "success", "message": "Done!"}\`
446
+ 5. Loop back to step 2
447
+ `;
448
+ if (fileExists(configPath)) {
449
+ log('Codex eyeglass instructions already exist', 'success');
450
+ return true;
451
+ }
452
+ if (dryRun) {
453
+ log(`Would create ${configPath}`);
454
+ }
455
+ else {
456
+ if (!fileExists(codexDir)) {
457
+ fs.mkdirSync(codexDir, { recursive: true });
458
+ }
459
+ writeFile(configPath, codexInstructions);
460
+ log('Created .codex/eyeglass.md with HTTP API instructions', 'success');
461
+ }
462
+ return true;
463
+ }
271
464
  function setupVite(configFile, dryRun) {
272
465
  const cwd = process.cwd();
273
466
  // Find entry file (main.tsx, main.ts, main.jsx, main.js, src/main.*, etc.)
@@ -402,12 +595,25 @@ function setupCRA(entryFile, dryRun) {
402
595
  }
403
596
  return true;
404
597
  }
405
- function init(options) {
598
+ async function init(options) {
406
599
  const { dryRun, skipInstall } = options;
407
- console.log('\n\x1b[1m🔍 Eyeglass Setup\x1b[0m\n');
600
+ let { agents } = options;
601
+ console.log(LOGO);
408
602
  if (dryRun) {
409
603
  log('Running in dry-run mode - no changes will be made\n', 'warn');
410
604
  }
605
+ // Prompt for agent selection if not provided
606
+ if (!agents || agents.length === 0) {
607
+ agents = await promptAgentSelection();
608
+ }
609
+ const agentNames = agents.map((a) => {
610
+ switch (a) {
611
+ case 'claude': return 'Claude Code';
612
+ case 'copilot': return 'GitHub Copilot CLI';
613
+ case 'codex': return 'OpenAI Codex CLI';
614
+ }
615
+ });
616
+ log(`Configuring for: ${agentNames.join(', ')}\n`);
411
617
  // Detect project
412
618
  const project = detectProject();
413
619
  log(`Detected: ${project.type}${project.typescript ? ' (TypeScript)' : ''}`);
@@ -426,10 +632,22 @@ function init(options) {
426
632
  }
427
633
  }
428
634
  }
429
- // Step 2: Setup Claude Code MCP config
430
- setupClaudeConfig(dryRun);
431
- // Step 3: Setup Eyeglass skill for Claude
432
- setupEyeglassSkill(dryRun);
635
+ // Step 2: Setup agent-specific configs
636
+ console.log('');
637
+ for (const agent of agents) {
638
+ switch (agent) {
639
+ case 'claude':
640
+ setupClaudeConfig(dryRun);
641
+ setupEyeglassSkill(dryRun);
642
+ break;
643
+ case 'copilot':
644
+ setupCopilotConfig(dryRun);
645
+ break;
646
+ case 'codex':
647
+ setupCodexConfig(dryRun);
648
+ break;
649
+ }
650
+ }
433
651
  // Step 4: Setup project-specific integration
434
652
  console.log('');
435
653
  switch (project.type) {
@@ -453,45 +671,75 @@ function init(options) {
453
671
  console.log(' 2. Or add <script type="module">import "@eyeglass/inspector";</script> to your HTML\n');
454
672
  }
455
673
  // Done!
456
- console.log('\n\x1b[1m✨ Setup complete!\x1b[0m\n');
674
+ console.log('\n\x1b[1mSetup complete!\x1b[0m\n');
675
+ printUsageInstructions(agents);
676
+ }
677
+ function printUsageInstructions(agents) {
457
678
  console.log('\x1b[1mHow to use Eyeglass:\x1b[0m\n');
458
679
  console.log(' 1. Start your dev server');
459
- console.log(' 2. Run \x1b[36mclaude\x1b[0m in this directory');
460
- console.log(' 3. Tell Claude: \x1b[36m"watch eyeglass"\x1b[0m or \x1b[36m"eg"\x1b[0m');
461
- console.log(' → Claude will start listening for requests');
462
- console.log(' 4. In your browser, hover over any element and click it to select for Eyeglass context. You can multi-select up to 5 items.');
463
- console.log(' 5. Type your request (e.g., "make this blue") and submit');
464
- console.log(' Claude automatically receives it and starts working!\n');
465
- console.log('\x1b[2mTip: You never need to leave your browser - Claude watches for requests.\x1b[0m\n');
680
+ console.log(' 2. Start the Eyeglass bridge: \x1b[36mnpx eyeglass-bridge\x1b[0m');
681
+ console.log('');
682
+ if (agents.includes('claude')) {
683
+ console.log(' \x1b[1mClaude Code:\x1b[0m');
684
+ console.log(' - Run \x1b[36mclaude\x1b[0m in this directory');
685
+ console.log(' - Say \x1b[36m"watch eyeglass"\x1b[0m or \x1b[36m"/eyeglass"\x1b[0m');
686
+ console.log('');
687
+ }
688
+ if (agents.includes('copilot')) {
689
+ console.log(' \x1b[1mGitHub Copilot CLI:\x1b[0m');
690
+ console.log(' - Run \x1b[36mgh copilot\x1b[0m in this directory');
691
+ console.log(' - Copilot will auto-connect to the eyeglass MCP server');
692
+ console.log('');
693
+ }
694
+ if (agents.includes('codex')) {
695
+ console.log(' \x1b[1mOpenAI Codex CLI:\x1b[0m');
696
+ console.log(' - See \x1b[36m.codex/eyeglass.md\x1b[0m for HTTP API docs');
697
+ console.log(' - Use \x1b[36mGET http://localhost:3300/api/wait\x1b[0m to listen');
698
+ console.log('');
699
+ }
700
+ console.log(' 3. In your browser, hover over any element and click to select');
701
+ console.log(' 4. Type your request (e.g., "make this blue") and submit');
702
+ console.log(' → Your agent automatically receives it and starts working!\n');
703
+ console.log('\x1b[2mTip: You never need to leave your browser - your agent watches for requests.\x1b[0m\n');
466
704
  }
467
705
  function help() {
468
- console.log(`
469
- \x1b[1mEyeglass\x1b[0m - Visual debugging for AI coding agents
706
+ console.log(LOGO);
707
+ console.log(`\x1b[2mVisual debugging for AI coding agents\x1b[0m
470
708
 
471
- Point at UI elements in your browser and tell Claude what to change.
472
- Claude watches for requests, so you never need to leave your browser.
709
+ Point at UI elements in your browser and tell your AI agent what to change.
710
+ Works with Claude Code, GitHub Copilot CLI, and OpenAI Codex CLI.
473
711
 
474
712
  \x1b[1mUSAGE\x1b[0m
475
713
  npx @eyeglass/cli <command> [options]
476
714
 
477
715
  \x1b[1mCOMMANDS\x1b[0m
478
- init Initialize Eyeglass in your project
716
+ init Initialize Eyeglass in your project (interactive)
479
717
  help Show this help message
480
718
 
481
719
  \x1b[1mOPTIONS\x1b[0m
482
720
  --dry-run Preview changes without making them
483
721
  --skip-install Skip installing @eyeglass/inspector
722
+ --claude Configure for Claude Code (stdio MCP)
723
+ --copilot Configure for GitHub Copilot CLI (local MCP)
724
+ --codex Configure for OpenAI Codex CLI (HTTP API)
484
725
 
485
726
  \x1b[1mEXAMPLES\x1b[0m
486
- npx @eyeglass/cli init # Full automatic setup
727
+ npx @eyeglass/cli init # Interactive agent selection
728
+ npx @eyeglass/cli init --claude # Setup for Claude Code only
729
+ npx @eyeglass/cli init --copilot --codex # Setup for multiple agents
487
730
  npx @eyeglass/cli init --dry-run # Preview what would change
488
731
 
732
+ \x1b[1mSUPPORTED AGENTS\x1b[0m
733
+ Claude Code - Uses stdio MCP (.claude/settings.json)
734
+ GitHub Copilot CLI - Uses local MCP (.copilot/mcp-config.json)
735
+ OpenAI Codex - Uses HTTP API (.codex/eyeglass.md)
736
+
489
737
  \x1b[1mWORKFLOW\x1b[0m
490
738
  1. Run \x1b[36mnpx @eyeglass/cli init\x1b[0m in your project
491
739
  2. Start your dev server
492
- 3. Run \x1b[36mclaude\x1b[0m and say "watch eyeglass" or "eg"
493
- 4. In your browser: hover over element → press E → type request
494
- 5. Claude automatically picks up requests and makes changes!
740
+ 3. Start your AI coding agent
741
+ 4. In your browser: hover over element → click → type request
742
+ 5. Your agent automatically picks up requests and makes changes!
495
743
 
496
744
  \x1b[1mMORE INFO\x1b[0m
497
745
  https://github.com/donutboyband/eyeglass
@@ -503,13 +751,25 @@ Claude watches for requests, so you never need to leave your browser.
503
751
  const args = process.argv.slice(2);
504
752
  const command = args.find((arg) => !arg.startsWith('-'));
505
753
  const flags = args.filter((arg) => arg.startsWith('-'));
754
+ // Parse agent flags
755
+ const agentFlags = [];
756
+ if (flags.includes('--claude'))
757
+ agentFlags.push('claude');
758
+ if (flags.includes('--copilot'))
759
+ agentFlags.push('copilot');
760
+ if (flags.includes('--codex'))
761
+ agentFlags.push('codex');
506
762
  const options = {
507
763
  dryRun: flags.includes('--dry-run'),
508
764
  skipInstall: flags.includes('--skip-install'),
765
+ agents: agentFlags.length > 0 ? agentFlags : undefined,
509
766
  };
510
767
  switch (command) {
511
768
  case 'init':
512
- init(options);
769
+ init(options).catch((err) => {
770
+ console.error('Error:', err.message);
771
+ process.exit(1);
772
+ });
513
773
  break;
514
774
  case 'help':
515
775
  case undefined:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eyeglass/cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Visual debugging for AI coding agents - CLI",
5
5
  "type": "module",
6
6
  "bin": {