@aayambansal/squint 0.1.0 → 0.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.
package/README.md CHANGED
@@ -1,58 +1,98 @@
1
- # squint
1
+ <div align="center">
2
2
 
3
- **Lovable for your terminal.** squint is a frontend harness that sits on top of the coding agents you already have — Claude Code, Codex CLI, Gemini CLI, OpenCode, Amp, Cursor CLI, Copilot CLI, Aider — and turns them into a design-obsessed app builder that works on **any repo**, local-first.
3
+ <pre>
4
+ ____ ___ _ _ ___ _ _ _____
5
+ / ___| / _ \| | | |_ _| \ | |_ _|
6
+ \___ \| | | | | | || || \| | | |
7
+ ___) | |_| | |_| || || |\ | | |
8
+ |____/ \__\_\\___/|___|_| \_| |_|
9
+ </pre>
4
10
 
5
- Lovable proved the loop: prompt → generate → preview → auto-fix → iterate. But it's a closed SaaS. You can't point it at an existing codebase, choose your agent or model, or own the loop. squint is that missing layer, in your terminal.
11
+ ### Lovable for your terminal
6
12
 
7
- ```
8
- ┌──────────────────────────────────────────────────────────┐
9
- │ ❯ make the pricing page feel premium │
10
- │ ⚙ Read · src/pages/Pricing.tsx │
11
- │ ⚙ Edit · src/pages/Pricing.tsx │
12
- │ Reworked the tier cards around a real type scale and │
13
- │ tightened the palette to ink + one accent… │
14
- │ · done · 41s · $0.18 │
15
- │ ✗ dev server: 1 error line(s) │
16
- │ error TS2304: Cannot find name 'Tier' │
17
- │ · auto-fix attempt 1/2 │
18
- │ ⛑ fix dev server errors │
19
- │ · done · 12s · $0.05 │
20
- │ │
21
- │ ❯ ▏ │
22
- │ claude · my-app · http://localhost:5173 · /help │
23
- └──────────────────────────────────────────────────────────┘
24
- ```
13
+ Any repo. Any coding agent. The whole loop, owned by you.
25
14
 
26
- ## The loop
15
+ [![npm](https://img.shields.io/npm/v/%40aayambansal%2Fsquint?color=2f5fe0)](https://www.npmjs.com/package/@aayambansal/squint)
16
+ [![ci](https://github.com/aayambansal/squint/actions/workflows/ci.yml/badge.svg)](https://github.com/aayambansal/squint/actions/workflows/ci.yml)
17
+ [![License](https://img.shields.io/badge/license-MIT-1a1a1a)](./LICENSE)
18
+ [![Engines](https://img.shields.io/badge/engines-8-2ea44f)](#engines)
19
+ [![PRs](https://img.shields.io/badge/PRs-welcome-2f5fe0)](./CONTRIBUTING.md)
20
+
21
+ </div>
22
+
23
+ ---
24
+
25
+ squint is a frontend harness that sits on top of the coding agents you already have — Claude
26
+ Code, Codex CLI, Gemini CLI, OpenCode, Amp, Cursor CLI, Copilot CLI, Aider — and turns them
27
+ into a design-obsessed app builder that works on any repo, local-first.
27
28
 
28
- 1. **You describe.** Every ask is wrapped in squint's design brief — an opinionated standard built from studying Lovable's leaked prompts, v0's design rules, and the documented catalog of "AI slop" tells: commit to a direction before code, tokens are the system, banned generic patterns, real craft details. Override per project with `.squint/brief.md`.
29
- 2. **Your agent builds.** squint drives whichever engine you choose, headlessly, streaming its work into the transcript token by token.
30
- 3. **The dev server judges.** squint runs your dev server, watches for build errors after every turn, and routes fresh breakage straight back to the engine (`/fix`, or automatic with `autoFix`).
31
- 4. **The runtime is watched.** After every clean turn, squint loads the page headlessly (CDP over Chrome, ~2s) and catches what the dev server never prints blank pages, uncaught exceptions, console errors, failed requests and feeds those back too.
32
- 5. **The agent looks at its work.** `/review` screenshots the running app at mobile/tablet/desktop and re-prompts the engine to critique what it can *see* — then fix it.
33
- 6. **Gates keep it honest.** `/check` runs typecheck → lint → test → build and feeds failures back, with instructions not to weaken the checks.
34
- 7. **Everything is reversible.** Each ask is snapshotted via git plumbing; `/undo` reverts the whole turn — while your own uncommitted work survives.
35
- 8. **Point at things.** `squint tag` (wired automatically in new apps) adds an element picker to your dev server: **Alt+S**, click any element, and a self-locating reference (`src/App.tsx <h1 class="…"> "Ready."`) lands on your clipboard to paste into squint.
36
- 9. **Explore in parallel.** `squint variants gen 3 "landing page for …"` builds the same ask three ways — three git worktrees, three *different* committed aesthetic directions, one screenshot each. Pick with your eyes, `squint variants apply <id>`.
29
+ Lovable proved the loop: prompt, generate, preview, auto-fix, iterate. But it's a closed SaaS.
30
+ You can't point it at an existing codebase, choose your agent or model, or own the loop.
31
+ squint is that missing layer, in your terminal. No cloud project, no lock-in, no secrets
32
+ storedAPI keys stay wherever your agent CLIs already read them.
37
33
 
38
- ## Install
34
+ ## Run it
39
35
 
40
36
  ```sh
41
- npm install -g @aayambansal/squint # then just: squint
42
- npx @aayambansal/squint # or run without installing
37
+ npx @aayambansal/squint # run without installing
38
+ npm install -g @aayambansal/squint # or install; then just: squint
43
39
  ```
44
40
 
45
- From source:
41
+ Start from nothing, like Lovable:
46
42
 
47
43
  ```sh
48
- git clone https://github.com/aayambansal/squint.git
49
- cd squint
50
- npm install && npm run build && npm link
44
+ squint init my-app # Vite + React + TS + Tailwind v4, token-first CSS
45
+ cd my-app && squint # open the TUI, describe what to build
51
46
  ```
52
47
 
53
- You need at least one engine installed (`squint doctor` shows what's found):
48
+ Or on any existing repo:
49
+
50
+ ```sh
51
+ cd your-project && squint
52
+ ```
54
53
 
55
- | Engine | id | Install |
54
+ From source: `git clone https://github.com/aayambansal/squint.git && cd squint && npm install && npm run build && npm link`.
55
+
56
+ ## The loop
57
+
58
+ ```
59
+ you describe ---> design brief ---> engine ---> edits land in your repo
60
+ ^ |
61
+ | +-----------------------------+
62
+ | | dev server build errors caught
63
+ | | CDP probe exceptions . console . 404s
64
+ | | a11y sweep alt text . labels . headings
65
+ | | screenshots 390 / 768 / 1440
66
+ | +-----------------------------+
67
+ | | |
68
+ +--- /undo reverts /fix (auto) /review: the agent
69
+ /variants explores critiques what it SEES
70
+ ```
71
+
72
+ 1. **You describe.** Every ask is wrapped in squint's design brief — built from studying
73
+ Lovable's leaked prompts, v0's design rules, and the documented catalog of AI-slop tells:
74
+ direction before code, tokens are the system, banned generic patterns. Override per
75
+ project with `.squint/brief.md`.
76
+ 2. **Your agent builds.** squint drives whichever engine you choose, headlessly, streaming
77
+ token by token.
78
+ 3. **The dev server judges.** Build errors after every turn route straight back to the
79
+ engine (`/fix`, or automatic with `autoFix`).
80
+ 4. **The runtime is watched.** After every clean turn squint loads the page headlessly (~2s)
81
+ and catches what the server never prints: blank pages, exceptions, failed requests.
82
+ 5. **The agent looks at its work.** `/review` screenshots mobile/tablet/desktop and
83
+ re-prompts the engine to critique what it can see — then fix it.
84
+ 6. **Gates keep it honest.** `/check` runs typecheck, lint, test, build — failures come
85
+ back with orders not to weaken the checks.
86
+ 7. **Everything is reversible.** Each ask is snapshotted via git plumbing; `/undo` reverts
87
+ the whole turn while your own uncommitted work survives.
88
+ 8. **Point at things.** Alt+S in the browser, click any element, and a self-locating
89
+ reference lands on your clipboard to paste into squint.
90
+ 9. **Explore in parallel.** `squint variants gen 3 "<ask>"` builds the same ask three ways —
91
+ three worktrees, three committed aesthetic directions. Pick with your eyes.
92
+
93
+ ## Engines
94
+
95
+ | engine | id | install |
56
96
  | --- | --- | --- |
57
97
  | Claude Code | `claude` | `npm i -g @anthropic-ai/claude-code` |
58
98
  | Codex CLI | `codex` | `npm i -g @openai/codex` |
@@ -63,88 +103,105 @@ You need at least one engine installed (`squint doctor` shows what's found):
63
103
  | Copilot CLI | `copilot` | `npm i -g @github/copilot` |
64
104
  | Aider | `aider` | `pip install aider-install && aider-install` |
65
105
 
66
- API keys stay wherever your agent CLIs already read them squint stores no secrets.
106
+ `squint doctor` shows what's found. One engine is enough; session resume works everywhere
107
+ the backend supports it (Claude, Codex, OpenCode, Amp, Cursor).
67
108
 
68
- ## Use
69
-
70
- **Start fresh** (Lovable-style, from nothing):
109
+ ## Commands
71
110
 
72
111
  ```sh
73
- squint init my-app # Vite + React + TS + Tailwind v4, token-first CSS
74
- cd my-app && squint # open the TUI, describe what to build
75
- ```
76
-
77
- **Or on any existing repo:**
78
-
79
- ```sh
80
- cd your-project && squint
81
- ```
82
-
83
- **Headless / scriptable:**
84
-
85
- ```sh
86
- squint run "add a dark mode toggle to the navbar"
112
+ squint # the TUI, in the current repo
113
+ squint run "add a dark mode toggle"
87
114
  squint run -e codex -m gpt-5 "tighten the hero spacing"
88
- squint run --json "" # normalized ndjson events for scripting
89
- squint check # quality gates: typecheck lint test build
115
+ squint run --json "..." # normalized ndjson events for scripting
116
+ squint check # gates: typecheck -> lint -> test -> build
90
117
  squint shot http://localhost:5173 # screenshots at 390/768/1440
91
- squint brief # list design directions; squint brief terminal commits one
92
- squint engines # what's installed
93
- squint doctor # engines + Chrome + WebSocket check
118
+ squint brief # list design directions
119
+ squint brief cinematic-dark # commit one for this repo
94
120
  squint tag # add the Alt+S element picker to any Vite app
95
- squint variants gen 3 "<ask>" # 3 parallel design explorations (3 engine runs)
96
- squint variants apply terminal # keep the winner, discard the rest
121
+ squint variants gen 3 "<ask>" # 3 parallel design explorations
122
+ squint variants apply terminal # keep the winner
123
+ squint config set engine claude
124
+ squint config set models.claude claude-sonnet-5
125
+ squint config set autoDev true # dev server starts with the TUI
126
+ squint config set autoFix true # errors auto-route back (max 2 tries)
127
+ squint doctor # engines + Chrome + WebSocket check
97
128
  ```
98
129
 
99
- **Commit a design direction** so every session holds the same look:
130
+ Inside the TUI: `/dev` `/check` `/fix` `/shot` `/review [focus]` `/undo` `/resume`
131
+ `/engine <id>` `/model <name>` `/clear` — `Esc` interrupts, arrows recall history.
100
132
 
101
- ```sh
102
- squint brief # editorial-minimal · terminal · warm-editorial · data-dense
103
- # cinematic-dark · playful · brutalist
104
- squint brief cinematic-dark # writes .squint/brief.md — plain markdown, made to remix
105
- ```
133
+ ## Design directions
106
134
 
107
- **Configure** (global `~/.config/squint/config.json`, per-repo `.squint/config.json`):
135
+ `squint brief` writes a committed direction to `.squint/brief.md` so every session holds the
136
+ same look. Seven families, organized by aesthetic rather than industry — the researched
137
+ cheapest route to non-generic work:
108
138
 
109
- ```sh
110
- squint config set engine claude
111
- squint config set models.claude claude-sonnet-5
112
- squint config set autoDev true # start the dev server with the TUI
113
- squint config set autoFix true # auto-send build/runtime errors back (max 2 tries)
114
- squint config set autoProbe false # disable the post-turn runtime probe
115
- squint config set --project engine codex # per-repo override
139
+ ```
140
+ editorial-minimal terminal warm-editorial data-dense
141
+ cinematic-dark playful brutalist
116
142
  ```
117
143
 
118
- **Inside the TUI:**
119
-
120
- | Command | What it does |
121
- | --- | --- |
122
- | `/dev` | start/stop the project dev server (auto-detected script + package manager) |
123
- | `/check` | run quality gates |
124
- | `/fix` | send captured errors / failed gates to the engine |
125
- | `/shot` | screenshot the app at mobile/tablet/desktop |
126
- | `/review [focus]` | screenshots + the engine critiques its own rendered work, then fixes it |
127
- | `/undo` | revert the whole last ask (your own uncommitted work survives) |
128
- | `/resume` | pick the previous session back up after a restart |
129
- | `/engine <id>` · `/model <name>` | switch backend or model mid-session |
130
- | `/clear` | new session |
131
- | `Esc` | interrupt the running turn · `↑/↓` prompt history |
144
+ Each is a concrete commitment — type pairing, color strategy, spacing rhythm, motion stance,
145
+ and an avoid-list tuned to that family's failure modes. Plain markdown, made to be remixed.
132
146
 
133
- ## Design decisions
147
+ ## How it fits together
134
148
 
135
- - **Engines are dumb translators.** Each adapter is ~80 lines: build a headless invocation, parse the stream into one normalized event model. Claude Code, Amp, and Cursor share a single wire-protocol parser. All product behavior lives in the harness, so adding an engine is cheap.
136
- - **The brief is the product.** Direction-before-code, token-first, banned-tells — encoded from research (`docs/research/`), not vibes.
137
- - **Zero-dependency eyes.** Screenshots use Chrome's own one-shot headless mode — no Playwright/Puppeteer install.
138
- - **Sessions resume** where engines support it (Claude `--resume`, Codex `exec resume`, OpenCode `--session`, Amp threads, Cursor chats).
149
+ ```
150
+ tui (ink) cli (run / check / shot / variants ...)
151
+ \ /
152
+ `-----------+---------------'
153
+ |
154
+ +------------------------+
155
+ | squint harness | brief . gates . fix loops
156
+ | prompt enrichment | snapshots . sessions
157
+ +-----+------------+-----+
158
+ | |
159
+ +----------+---+ +---+---------------------+
160
+ | engine layer | | eyes |
161
+ | 8 adapters, | | dev-server watcher |
162
+ | one event | | CDP runtime + a11y |
163
+ | stream | | headless screenshots |
164
+ +------+-------+ +-------------------------+
165
+ |
166
+ claude . codex . gemini . opencode . amp . cursor . copilot . aider
167
+ ```
139
168
 
140
- ## Roadmap
169
+ Engines are dumb translators: build a headless invocation, parse the stream into one
170
+ normalized event model. Claude Code, Amp, and Cursor share a single wire-protocol parser.
171
+ All product behavior lives in the harness, so a new engine is ~80 lines.
141
172
 
142
- - npm distribution
143
- - Variants inside the TUI with an inline picker
144
- - Deeper gates: axe accessibility audits, Lighthouse budgets, visual regression baselines
173
+ ## Repo layout
145
174
 
146
- Architecture notes in `docs/design/`, research base in `docs/research/`.
175
+ | path | what it is |
176
+ | --- | --- |
177
+ | `src/engines` | 8 adapters + the shared Claude wire-protocol parser |
178
+ | `src/runner` | subprocess spawn → normalized event stream, abort support |
179
+ | `src/prompt` | the design brief + 7 aesthetic families |
180
+ | `src/devserver` | dev-server manager + build-error detection |
181
+ | `src/preview` | Chrome discovery, CDP client, screenshots, a11y sweep |
182
+ | `src/gates` | quality gates (typecheck / lint / test / build) |
183
+ | `src/tagger` | the Alt+S element picker (embedded Vite plugin) |
184
+ | `src/variants` | parallel exploration worktrees |
185
+ | `src/scaffold` | the `squint init` template |
186
+ | `src/vcs` | `/undo` git snapshots |
187
+ | `src/state` | per-project session persistence |
188
+ | `src/tui` | the Ink app |
189
+ | `docs/research` | the knowledge base squint is built from |
190
+
191
+ ## Docs
192
+
193
+ - [Architecture](./docs/design/2026-07-25-architecture.md)
194
+ - [How Lovable works under the hood](./docs/research/lovable.md)
195
+ - [Making agents produce excellent frontend work](./docs/research/frontend-quality.md)
196
+ - [Engine headless interfaces + TUI stack](./docs/research/engines-and-tui.md)
197
+ - [Changelog](./CHANGELOG.md)
198
+
199
+ ## Contributing
200
+
201
+ Built in the open, moving fast. Every change ships as a pull request with CI green. See
202
+ [CONTRIBUTING.md](./CONTRIBUTING.md) — adding an engine adapter is the best first issue
203
+ there is.
147
204
 
148
205
  ## License
149
206
 
150
- MIT © Aayam Bansal
207
+ [MIT](./LICENSE) © Aayam Bansal. Take it, run it, ship it.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  cdpCapture,
4
4
  hasWebSocket
5
- } from "./chunk-OJTW5SYY.js";
5
+ } from "./chunk-ABF4QAMZ.js";
6
6
  export {
7
7
  cdpCapture,
8
8
  hasWebSocket
@@ -5,6 +5,37 @@ import { spawn } from "child_process";
5
5
  import fs from "fs";
6
6
  import os from "os";
7
7
  import path from "path";
8
+ var A11Y_AUDIT = `(() => {
9
+ const out = [];
10
+ const name = (el) => (el.getAttribute('aria-label') || el.textContent || el.getAttribute('title') || '').trim();
11
+ const short = (el) => '<' + el.tagName.toLowerCase() + (el.id ? '#' + el.id : '') + (el.className && typeof el.className === 'string' ? '.' + el.className.split(/\\s+/).slice(0, 2).join('.') : '') + '>';
12
+ if (!document.documentElement.getAttribute('lang')) out.push('document missing lang attribute');
13
+ if (!document.title.trim()) out.push('document missing <title>');
14
+ for (const img of document.querySelectorAll('img:not([alt])')) out.push('img missing alt: ' + (img.getAttribute('src') || '').split('/').pop());
15
+ for (const el of document.querySelectorAll('button, a[href]')) {
16
+ if (!name(el) && !el.querySelector('img[alt]')) out.push(el.tagName.toLowerCase() + ' without accessible name ' + short(el));
17
+ }
18
+ for (const el of document.querySelectorAll('input:not([type=hidden]), select, textarea')) {
19
+ const labelled = el.getAttribute('aria-label') || el.getAttribute('aria-labelledby') || el.closest('label') || (el.id && document.querySelector('label[for="' + el.id + '"]'));
20
+ if (!labelled) out.push('form control without label ' + short(el));
21
+ }
22
+ let last = 0;
23
+ for (const h of document.querySelectorAll('h1,h2,h3,h4,h5,h6')) {
24
+ const level = Number(h.tagName[1]);
25
+ if (last && level > last + 1) out.push('heading order jumps h' + last + ' \u2192 h' + level + ' ' + short(h));
26
+ last = level;
27
+ }
28
+ let tiny = 0;
29
+ for (const el of document.querySelectorAll('button, a[href]')) {
30
+ const r = el.getBoundingClientRect();
31
+ if (r.width > 0 && (r.width < 24 || r.height < 24)) tiny++;
32
+ }
33
+ if (tiny > 0) out.push(tiny + ' interactive element(s) smaller than 24x24px');
34
+ for (const el of document.querySelectorAll('[tabindex]')) {
35
+ if (Number(el.getAttribute('tabindex')) > 0) out.push('positive tabindex ' + short(el));
36
+ }
37
+ return out.slice(0, 20);
38
+ })()`;
8
39
  function hasWebSocket() {
9
40
  return typeof globalThis.WebSocket === "function";
10
41
  }
@@ -118,10 +149,11 @@ var describe = (value) => {
118
149
  }
119
150
  return String(value);
120
151
  };
121
- async function cdpCapture(chromePath, url, outDir, viewports, settleMs = 2500) {
152
+ async function cdpCapture(chromePath, url, outDir, viewports, settleMs = 2500, audit = false) {
122
153
  const { child, wsUrl, profileDir } = await launchChrome(chromePath);
123
154
  const report = { consoleErrors: [], pageErrors: [], failedRequests: [] };
124
155
  const shots = [];
156
+ let a11y = [];
125
157
  const requests = /* @__PURE__ */ new Map();
126
158
  let connection = null;
127
159
  try {
@@ -166,6 +198,17 @@ async function cdpCapture(chromePath, url, outDir, viewports, settleMs = 2500) {
166
198
  await new Promise((resolve) => setTimeout(resolve, 100));
167
199
  }
168
200
  await new Promise((resolve) => setTimeout(resolve, settleMs));
201
+ if (audit) {
202
+ try {
203
+ const { result } = await connection.send(
204
+ "Runtime.evaluate",
205
+ { expression: A11Y_AUDIT, returnByValue: true },
206
+ sessionId
207
+ );
208
+ if (Array.isArray(result?.value)) a11y = result.value.map(String);
209
+ } catch {
210
+ }
211
+ }
169
212
  for (const viewport of viewports) {
170
213
  await connection.send(
171
214
  "Emulation.setDeviceMetricsOverride",
@@ -188,7 +231,7 @@ async function cdpCapture(chromePath, url, outDir, viewports, settleMs = 2500) {
188
231
  child.kill("SIGKILL");
189
232
  setTimeout(() => fs.rmSync(profileDir, { recursive: true, force: true }), 500).unref?.();
190
233
  }
191
- return { report, shots };
234
+ return { report, shots, a11y };
192
235
  }
193
236
 
194
237
  export {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  cdpCapture,
4
4
  hasWebSocket
5
- } from "./chunk-OJTW5SYY.js";
5
+ } from "./chunk-ABF4QAMZ.js";
6
6
  import {
7
7
  findChrome,
8
8
  screenshot
@@ -74,8 +74,8 @@ async function captureViewports(cwd, url) {
74
74
  const dir = previewDir(cwd);
75
75
  if (hasWebSocket()) {
76
76
  try {
77
- const { report, shots: shots2 } = await cdpCapture(chrome, url, dir, VIEWPORTS);
78
- return { shots: shots2, errors: [], runtime: report };
77
+ const { report, shots: shots2, a11y } = await cdpCapture(chrome, url, dir, VIEWPORTS, 2500, true);
78
+ return { shots: shots2, errors: [], runtime: report, a11y };
79
79
  } catch {
80
80
  }
81
81
  }
@@ -141,13 +141,23 @@ function buildRuntimeFixPrompt(report) {
141
141
 
142
142
  Diagnose and fix the root causes, then confirm the app loads clean.`;
143
143
  }
144
- function buildReviewPrompt(shots, extra, runtime) {
144
+ function a11ySection(findings) {
145
+ if (!findings || findings.length === 0) return "";
146
+ return `
147
+
148
+ ## Accessibility sweep findings
149
+
150
+ ${findings.join("\n")}
151
+
152
+ Fix these as part of the pass \u2014 they are objective defects, not style preferences.`;
153
+ }
154
+ function buildReviewPrompt(shots, extra, runtime, a11y) {
145
155
  const list = shots.map((s) => `- ${s.name}: ${s.path}`).join("\n");
146
156
  return `Screenshots of the running app were just captured:
147
157
 
148
158
  ${list}
149
159
 
150
- Read each screenshot and review the rendered UI against the design standards you were given. Check: visual hierarchy and spacing rhythm, typography, color and contrast, alignment, empty-looking or broken regions, and whether the mobile capture shows horizontal overflow or cramped layout. List the concrete issues you can SEE (not hypothetical ones), ranked by visual impact${extra ? `, with special attention to: ${extra}` : ""}. Then fix them and verify the app still builds.${runtimeSection(runtime)}`;
160
+ Read each screenshot and review the rendered UI against the design standards you were given. Check: visual hierarchy and spacing rhythm, typography, color and contrast, alignment, empty-looking or broken regions, and whether the mobile capture shows horizontal overflow or cramped layout. List the concrete issues you can SEE (not hypothetical ones), ranked by visual impact${extra ? `, with special attention to: ${extra}` : ""}. Then fix them and verify the app still builds.${runtimeSection(runtime)}${a11ySection(a11y)}`;
151
161
  }
152
162
 
153
163
  export {
package/dist/cli.js CHANGED
@@ -24,8 +24,8 @@ import {
24
24
  probeRuntime,
25
25
  runtimeSummary,
26
26
  saveState
27
- } from "./chunk-4XHTAWTH.js";
28
- import "./chunk-OJTW5SYY.js";
27
+ } from "./chunk-MOYLED4S.js";
28
+ import "./chunk-ABF4QAMZ.js";
29
29
  import "./chunk-MURKQ7SI.js";
30
30
  import {
31
31
  detectEngines,
@@ -409,6 +409,11 @@ ${errors.slice(-5).join("\n")}`);
409
409
  push("status", "runtime clean \u2014 no console errors, exceptions, or failed requests");
410
410
  }
411
411
  }
412
+ if (result.a11y && result.a11y.length > 0) {
413
+ push("error", `a11y: ${result.a11y.length} finding(s)
414
+ ${result.a11y.slice(0, 5).join("\n")}`);
415
+ push("status", "/review folds these into the fix pass");
416
+ }
412
417
  return result.shots.length > 0 ? result : null;
413
418
  }, [cwd, devUrl, push]);
414
419
  const submit = useCallback(
@@ -505,7 +510,7 @@ ${errors.slice(-5).join("\n")}`);
505
510
  const result = await capture();
506
511
  if (result) {
507
512
  await runTurn(
508
- buildReviewPrompt(result.shots, arg || void 0, result.runtime),
513
+ buildReviewPrompt(result.shots, arg || void 0, result.runtime, result.a11y),
509
514
  `\u{1F441} review rendered UI${arg ? ` \xB7 ${arg}` : ""}`
510
515
  );
511
516
  }
@@ -646,7 +651,7 @@ ${errors.slice(-5).join("\n")}`);
646
651
 
647
652
  // src/cli.tsx
648
653
  import { jsx as jsx3 } from "react/jsx-runtime";
649
- var VERSION = "0.1.0";
654
+ var VERSION = "0.1.1";
650
655
  var program = new Command();
651
656
  program.name("squint").description("Lovable for your terminal \u2014 a frontend harness on top of Claude Code, Codex, and friends.").version(VERSION);
652
657
  program.command("run").description("Run one prompt headlessly and stream the result").argument("<prompt...>", "what to build or change").option("-e, --engine <id>", "engine to use (claude, codex, gemini, opencode)").option("-m, --model <name>", "model override for the engine").option("--no-brief", "send the prompt without the squint design brief").option("--json", "emit normalized agent events as ndjson").action(
@@ -690,7 +695,7 @@ program.command("doctor").description("Check squint prerequisites and engine ava
690
695
  console.log(`${status} ${engine.name}${binaryPath ? "" : pc.dim(` \u2014 install: ${engine.install}`)}`);
691
696
  }
692
697
  const { findChrome } = await import("./chrome-4WNYZZ42.js");
693
- const { hasWebSocket } = await import("./cdp-5OHNGQXV.js");
698
+ const { hasWebSocket } = await import("./cdp-R7Y2XSZQ.js");
694
699
  const chrome = findChrome();
695
700
  console.log(
696
701
  chrome ? `${pc.green("\u2713")} Chrome ${pc.dim(chrome)}` : `${pc.yellow("\u25CB")} Chrome ${pc.dim("\u2014 screenshots and runtime probing disabled")}`
@@ -881,7 +886,7 @@ program.command("check").description("Run this project\u2019s quality gates (typ
881
886
  if (results.some((r) => !r.ok)) process.exitCode = 1;
882
887
  });
883
888
  program.command("shot").description("Screenshot a running app at mobile/tablet/desktop viewports").argument("<url>", "URL of the running app (e.g. http://localhost:5173)").action(async (url) => {
884
- const { captureViewports: captureViewports2 } = await import("./preview-5PCHDJL7.js");
889
+ const { captureViewports: captureViewports2 } = await import("./preview-AA6YIE5W.js");
885
890
  const result = await captureViewports2(process.cwd(), url);
886
891
  if (!result) {
887
892
  console.error(pc.red("\u2717 no Chrome/Chromium found"));
@@ -7,8 +7,8 @@ import {
7
7
  previewDir,
8
8
  probeRuntime,
9
9
  runtimeSummary
10
- } from "./chunk-4XHTAWTH.js";
11
- import "./chunk-OJTW5SYY.js";
10
+ } from "./chunk-MOYLED4S.js";
11
+ import "./chunk-ABF4QAMZ.js";
12
12
  import "./chunk-MURKQ7SI.js";
13
13
  import "./chunk-YIVPCWSG.js";
14
14
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aayambansal/squint",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Lovable for your terminal — a frontend harness on top of Claude Code, Codex, and other coding agents.",
5
5
  "type": "module",
6
6
  "license": "MIT",