Files
pbakaus_impeccable/bin/cli.js
T
Paul BakausandClaude Opus 4.6 bb94dadda0 Add live variant mode: element picker, action panel, poll/reply bridge (22 commands)
New feature: /impeccable live starts an interactive visual iteration server.
Users select elements in the browser, pick a design action (bolder, quieter,
etc.), and the agent generates HTML+CSS variants written directly to source.
The dev server's HMR hot-swaps them in, and MutationObserver progressively
reveals each variant in a cycler UI as it arrives.

Architecture:
- src/live/server.mjs: HTTP + WebSocket server with session token auth,
  long-poll /poll endpoint for the agent, WebSocket for the browser
- src/live/poll.mjs: CLI client (npx impeccable poll / poll --reply)
- src/live/browser.js: element picker with keyboard nav (arrows=siblings,
  shift+arrows=parent/child), action panel (12 commands, freeform input,
  variant count), variant cycler with progressive reveal via MutationObserver
- src/live/protocol.mjs: shared message types and event validation
- source/skills/impeccable/reference/live.md: agent loop instructions
  (inject script, poll loop, generate variants, accept/discard, cleanup)

CLI changes:
- bin/cli.js: added "poll" top-level command
- src/detect-antipatterns.mjs: liveCli() now delegates to src/live/server.mjs
- package.json: added ws dependency

Registered /impeccable live as command #22 across all standard locations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:13:53 -07:00

71 lines
2.6 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* Impeccable CLI
*
* Usage:
* npx impeccable detect [file-or-dir-or-url...]
* npx impeccable live [--port=PORT]
* npx impeccable live stop
* npx impeccable skills help|install|update
* npx impeccable --help
*/
import { readFileSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const args = process.argv.slice(2);
const command = args[0];
if (!command || command === '--help' || command === '-h') {
console.log(`Usage: impeccable <command> [options]
Commands:
detect [file-or-dir-or-url...] Scan for UI anti-patterns and design quality issues
live [--port=PORT] Start live variant server (element picker + variant cycling)
live stop Stop a running live server
poll Wait for a browser event from the live server
poll --reply <id> <status> Reply to a pending event (done, error)
skills help List all available skills and commands
skills install Install impeccable skills into your project
skills update Update skills to the latest version
skills check Check if skill updates are available
Options:
--help Show this help message
--version Show version number
Run 'impeccable <command> --help' for command-specific options.`);
process.exit(0);
}
if (command === '--version' || command === '-v') {
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
console.log(pkg.version);
process.exit(0);
}
if (command === 'detect') {
process.argv = [process.argv[0], process.argv[1], ...args.slice(1)];
const { detectCli } = await import('../src/detect-antipatterns.mjs');
await detectCli();
} else if (command === 'live') {
process.argv = [process.argv[0], process.argv[1], ...args.slice(1)];
const { liveCli } = await import('../src/detect-antipatterns.mjs');
await liveCli();
} else if (command === 'poll') {
process.argv = [process.argv[0], process.argv[1], ...args.slice(1)];
const { pollCli } = await import('../src/live/poll.mjs');
await pollCli();
} else if (command === 'skills') {
const { run } = await import('./commands/skills.mjs');
await run(args.slice(1));
} else {
// Default: treat as detect arguments (allow `npx impeccable src/` shorthand)
process.argv = [process.argv[0], process.argv[1], ...args];
const { detectCli } = await import('../src/detect-antipatterns.mjs');
await detectCli();
}