diff --git a/docs/CHROME_WEB_STORE.md b/docs/CHROME_WEB_STORE.md index 6e5b96b..966d671 100644 --- a/docs/CHROME_WEB_STORE.md +++ b/docs/CHROME_WEB_STORE.md @@ -101,21 +101,30 @@ repo must be public for it to resolve). ## Graphic assets The **Graphic assets** section of the listing form. Ready-made, branded assets -live in [`packages/extension/store-assets/`](../packages/extension/store-assets) -(regenerate with `python3 packages/extension/store-assets/generate.py`). +live in [`packages/extension/store-assets/`](../packages/extension/store-assets). +All of them are HTML in `store-assets/screens/` (the popup screenshot frames +the real `popup.css`); re-render with `store-assets/screens/render.sh`. | Slot | Required | Size | Format | Use | |---|---|---|---|---| | **Store icon** | ✅ | 128×128 | PNG | `packages/extension/icons/icon-128.png` | -| **Screenshots** (≤5) | ✅ (≥1) | 1280×800 or 640×400 | JPEG / 24-bit PNG, no alpha | `store-assets/screenshot-1280x800.png` | +| **Screenshots** (≤5) | ✅ (≥1) | 1280×800 or 640×400 | JPEG / 24-bit PNG, no alpha | `store-assets/screenshot-{1..5}-1280x800.png`, uploaded in order | | **Small promo tile** | optional | 440×280 | JPEG / 24-bit PNG, no alpha | `store-assets/small-tile-440x280.png` | | **Marquee promo tile** | optional | 1400×560 | JPEG / 24-bit PNG, no alpha | `store-assets/marquee-1400x560.png` | | Global promo video | optional | — | YouTube URL | skip | -The generated screenshot is a **branded hero** — enough to submit. For a -stronger listing, add real captures too (up to 5): the toolbar popover in its -connected state, and an agent driving a page. Capture at exactly 1280×800 (or -640×400) with no alpha channel. +The five screenshots, in upload order: + +1. **Hero**: an agent driving a signed-in page, refs on the elements, Chrome's + debugging banner showing. +2. **Site permissions**: the popup, connected, with deny / read / full rules. +3. **`reins do`**: one command for a whole task, with the benchmark medians. +4. **Debugging**: console errors and a failing request, read from the shell. +5. **Local-only**: agent → daemon on 127.0.0.1 → extension, and the facts. + +Terminal output in them follows the CLI's real formats; if a formatter +changes, update the matching slide. Slide 3's figures come from +`packages/web/src/routes/docs/benchmarks.tsx`. ## Store listing description (paste-ready) diff --git a/packages/extension/store-assets/generate.py b/packages/extension/store-assets/generate.py deleted file mode 100644 index b2195ed..0000000 --- a/packages/extension/store-assets/generate.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python3 -"""Generate reins Chrome Web Store graphic assets (exact sizes, 24-bit, no alpha). - -Run: python3 generate.py (needs Pillow; macOS system fonts) -Outputs PNGs next to this file. Regenerate whenever the branding changes. -""" -import os -from PIL import Image, ImageDraw, ImageFont - -HERE = os.path.dirname(os.path.abspath(__file__)) -C0 = (124, 131, 255) # #7C83FF -C1 = (109, 40, 217) # #6D28D9 -WHITE = (255, 255, 255) -INK = (14, 16, 32) - -FONT_CANDIDATES = [ - "/System/Library/Fonts/Helvetica.ttc", - "/System/Library/Fonts/HelveticaNeue.ttc", - "/System/Library/Fonts/Supplemental/Arial.ttf", -] -MONO_CANDIDATES = [ - "/System/Library/Fonts/Menlo.ttc", - "/System/Library/Fonts/SFNSMono.ttf", - "/System/Library/Fonts/Courier.ttc", -] - - -def font(size, bold=False, mono=False): - cands = MONO_CANDIDATES if mono else FONT_CANDIDATES - for path in cands: - if os.path.exists(path): - try: - # .ttc index 1 is often the bold/variant face; fall back to 0. - return ImageFont.truetype(path, size, index=1 if bold and path.endswith(".ttc") else 0) - except Exception: - try: - return ImageFont.truetype(path, size) - except Exception: - continue - return ImageFont.load_default() - - -def gradient(w, h): - """Diagonal gradient C0 (top-left) → C1 (bottom-right).""" - img = Image.new("RGB", (w, h)) - px = img.load() - denom = float(w + h - 2) or 1.0 - # Precompute per-diagonal color for speed. - row = [None] * (w + h) - for s in range(w + h): - t = s / denom - row[s] = ( - int(C0[0] + (C1[0] - C0[0]) * t), - int(C0[1] + (C1[1] - C0[1]) * t), - int(C0[2] + (C1[2] - C0[2]) * t), - ) - for y in range(h): - for x in range(w): - px[x, y] = row[x + y] - return img - - -def cubic(p0, p1, p2, p3, n=48): - pts = [] - for i in range(n + 1): - t = i / n - u = 1 - t - x = u * u * u * p0[0] + 3 * u * u * t * p1[0] + 3 * u * t * t * p2[0] + t * t * t * p3[0] - y = u * u * u * p0[1] + 3 * u * u * t * p1[1] + 3 * u * t * t * p2[1] + t * t * t * p3[1] - pts.append((x, y)) - return pts - - -def draw_mark(img, x, y, size): - """The reins logo mark: white rounded tile + two grips + connecting spline.""" - d = ImageDraw.Draw(img) - s = size - d.rounded_rectangle([x, y, x + s, y + s], radius=int(s * 0.24), fill=WHITE) - - def P(fx, fy): - return (x + fx * s, y + fy * s) - - curve = cubic(P(0.33, 0.33), P(0.33, 0.62), P(0.67, 0.40), P(0.67, 0.67)) - d.line(curve, fill=C1, width=max(3, int(s * 0.095)), joint="curve") - r = s * 0.11 - for cx, cy in (P(0.33, 0.33), P(0.67, 0.67)): - d.ellipse([cx - r, cy - r, cx + r, cy + r], fill=C1) - - -def text(d, xy, s, fnt, fill=WHITE, anchor="la"): - d.text(xy, s, font=fnt, fill=fill, anchor=anchor) - - -def marquee(): - w, h = 1400, 560 - img = gradient(w, h) - draw_mark(img, 150, 170, 220) - d = ImageDraw.Draw(img) - text(d, (440, 130), "reins", font(150, bold=True)) - text(d, (446, 300), "Drive your real browser from your coding agent.", font(40, bold=True)) - text(d, (446, 362), "npm i -g @karnstack/reins", font(30, mono=True), fill=(235, 236, 247)) - img.save(os.path.join(HERE, "marquee-1400x560.png")) - - -def small_tile(): - w, h = 440, 280 - img = gradient(w, h) - draw_mark(img, 40, 42, 96) - d = ImageDraw.Draw(img) - text(d, (158, 52), "reins", font(58, bold=True)) - text(d, (40, 176), "Drive your real browser", font(27, bold=True)) - text(d, (40, 212), "from your coding agent.", font(27, bold=True)) - img.save(os.path.join(HERE, "small-tile-440x280.png")) - - -def screenshot(): - w, h = 1280, 800 - img = gradient(w, h) - draw_mark(img, 120, 96, 132) - d = ImageDraw.Draw(img) - text(d, (284, 92), "reins", font(96, bold=True)) - text(d, (290, 190), "Drive your real, logged-in browser from your coding agent.", font(33, bold=True)) - - # terminal card - d.rounded_rectangle([120, 300, 1160, 704], radius=20, fill=INK) - for i, cx in enumerate((150, 178, 206)): - col = [(255, 95, 87), (254, 188, 46), (40, 200, 64)][i] - d.ellipse([cx - 8, 26 + 300, cx + 8, 42 + 300], fill=col) - mono = font(25, mono=True) - green = (155, 231, 166) - fg = (237, 238, 247) - muted = (138, 143, 176) - lines = [ - (green, "$ ", fg, "reins tabs"), - (muted, " b1 tab 12 * Docs — https://example.com", None, None), - (green, "$ ", fg, "reins snapshot --tab 12"), - (muted, ' e5: button "Submit"', None, None), - (green, "$ ", fg, "reins click --ref e5"), - (muted, " ok", None, None), - ] - y = 380 - for c0, t0, c1, t1 in lines: - d.text((150, y), t0, font=mono, fill=c0) - if t1: - w0 = d.textlength(t0, font=mono) - d.text((150 + w0, y), t1, font=mono, fill=c1) - y += 50 - text(d, (120, 748), "Local-only · tabs · click · type · screenshot · console & network · raw CDP", - font(24, bold=True), fill=(235, 236, 247)) - img.save(os.path.join(HERE, "screenshot-1280x800.png")) - - -if __name__ == "__main__": - marquee() - small_tile() - screenshot() - print("generated marquee / small-tile / screenshot PNGs") diff --git a/packages/extension/store-assets/marquee-1400x560.png b/packages/extension/store-assets/marquee-1400x560.png index 4174dc8..8ab3826 100644 Binary files a/packages/extension/store-assets/marquee-1400x560.png and b/packages/extension/store-assets/marquee-1400x560.png differ diff --git a/packages/extension/store-assets/screens/1-hero.html b/packages/extension/store-assets/screens/1-hero.html new file mode 100644 index 0000000..d80c3a2 --- /dev/null +++ b/packages/extension/store-assets/screens/1-hero.html @@ -0,0 +1,103 @@ + + + + + + + + +
+
+ reins + reins.tech +
+

#Drive the browser you're signed in to

+

Your coding agent gets your real Chrome, logins and all. No debug profile, no launch flags, no signing in again.

+ +
+
+
+
+
Pull requests
+ agent +
Invoices · Acme
+
Stripe export
+
+
+ +
🔒app.acme.dev/billing/invoices
+
+
+
"reins" started debugging this browserCancel
+
+
+ + Overview + Customers + Invoices + Payouts + Settings +
+
+

Invoices

maya@acme.dev
+
+ +
Filter
+
e7Export CSV
+ +
+ + + + + + + +
InvoiceCustomerAmountStatus
e12INV-2041Northwind$4,200.00
INV-2040Globex$1,180.00Due
INV-2039Initech$9,640.00
INV-2038Umbrella$720.00
INV-2037Hooli$3,015.00Due
+
+
+
+ +
+
claude — ~/acme
+
$ reins snapshot
+e7: button "Export CSV"
+e9: textbox "Search invoices"
+e12: link "INV-2041"
+$ reins click --ref e7
+ok
+$ reins text
+Export ready: invoices-2026-09.csv
+$ 
+
+
+
+ + diff --git a/packages/extension/store-assets/screens/2-popup.html b/packages/extension/store-assets/screens/2-popup.html new file mode 100644 index 0000000..be73993 --- /dev/null +++ b/packages/extension/store-assets/screens/2-popup.html @@ -0,0 +1,56 @@ + + + + + + + + +
+
+
+
reins
+

#You decide what it can touch

+

Every site resolves to one tier, checked inside the extension before a command reaches the tab. Granting more takes a click here. An agent in your shell can't make one.

+
    +
  • denyNothing. The site's tabs are hidden from the agent.
  • +
  • readSnapshot, text, screenshot. No clicks, no typing.
  • +
  • fullEverything, including eval and raw CDP.
  • +
+
+
+
+
+
+
My Bank · Accounts
+
+
+ +
🔒mybank.com/accounts
+
+
+
+
+
+
+
+
+ + diff --git a/packages/extension/store-assets/screens/3-do.html b/packages/extension/store-assets/screens/3-do.html new file mode 100644 index 0000000..e322a32 --- /dev/null +++ b/packages/extension/store-assets/screens/3-do.html @@ -0,0 +1,51 @@ + + + + + + + + +
+
+ reins + reins.tech +
+

#Hand off the whole taskNEW

+

reins do gives a browsing goal to Jev, TypeSafe's action model. Jev picks each click in about 0.2 s. Your agent supplies the values and checks the result.

+ +
+
+
claude — ~/app
+
$ reins do 'find the package and open it' --fill query=zod
+done in 3.5s · 3 steps · 4 jev calls · 16k tokens · self-check 0.94
+  1 click  "Search packages"
+  2 type   "Search packages" ← query
+  3 click  "zod"
+now: https://www.npmjs.com/package/zod — "zod - npm"
+next: reins snapshot   # verify before trusting DONE
+$ reins snapshot
+e2: link "zod"
+e5: button "Copy install command"
+$ 
+
+
+
+
4.6×faster, median
+
~100×cheaper, median
+
+

vs. the agent clicking step by step, on the reins benchmark. Optional: needs a TypeSafe key.

+
+
+
+ + diff --git a/packages/extension/store-assets/screens/4-debug.html b/packages/extension/store-assets/screens/4-debug.html new file mode 100644 index 0000000..fcc1341 --- /dev/null +++ b/packages/extension/store-assets/screens/4-debug.html @@ -0,0 +1,77 @@ + + + + + + + + +
+
+ reins + reins.tech +
+

#Console and network, no DevTools

+

Your agent reads the page's errors and failed requests on its own, then goes and fixes the code that caused them.

+ +
+
+
+
+
Checkout · Acme Shop
+
Orders · Admin
+
+
+ +
localhost:5173/checkout
+
+
+
"reins" started debugging this browserCancel
+
+ +

Checkout

+
+
Trail runner ×1$128.00
+
Wool socks ×2$36.00
+
Shipping$6.00
+
Total$NaN
+
Pay now
+
+
+
Something went wrong placing your order. Please try again.
+
+ +
+
claude — ~/shop
+
$ reins console --level error
+[error] TypeError: Cannot read properties of undefined (reading 'price')
+[error] checkout failed: 500 Internal Server Error
+$ reins network --url /api
+GET http://localhost:5173/api/cart -> 200
+GET http://localhost:5173/api/shipping -> 200
+POST http://localhost:5173/api/checkout -> 500
+$ reins eval 'window.__cart.items.length'
+3
+$ 
+
+
+
+ + diff --git a/packages/extension/store-assets/screens/5-local.html b/packages/extension/store-assets/screens/5-local.html new file mode 100644 index 0000000..0d386e7 --- /dev/null +++ b/packages/extension/store-assets/screens/5-local.html @@ -0,0 +1,52 @@ + + + + + + + + +
+
+ reins + reins.tech +
+

#Everything runs on your machine

+

The CLI, a daemon it starts on demand, and this extension talk over 127.0.0.1. Chrome shows its debugging banner the whole time, and Disconnect cuts it off.

+ +
+ your machine +
+
your agentreins <cmd>Claude Code, Cursor, Codex…
+
+
daemon127.0.0.1:8765starts on demand
+
+
this extensionyour browserchrome.debugger → tab
+
+
+
hosted serviceNone
+
accountNone
+
telemetryNone. No analytics, no remote code
+
licenseMIT, open source
+
browsersChrome, Brave, Edge, Arc, Dia
+
install the CLInpm i -g @karnstack/reins
+
+
+
+ + diff --git a/packages/extension/store-assets/screens/logo.svg b/packages/extension/store-assets/screens/logo.svg new file mode 100644 index 0000000..5279747 --- /dev/null +++ b/packages/extension/store-assets/screens/logo.svg @@ -0,0 +1 @@ + diff --git a/packages/extension/store-assets/screens/popup-frame.html b/packages/extension/store-assets/screens/popup-frame.html new file mode 100644 index 0000000..6cfbfe5 --- /dev/null +++ b/packages/extension/store-assets/screens/popup-frame.html @@ -0,0 +1,83 @@ + + + + + + + + + +
+
+ +
+

reins

+

Drive this browser from your agent

+
+ + + Connected + +
+ +
+
Daemon
v0.6.0 · 127.0.0.1:8765
+
This browser
b1 (Chrome)
+
+ + + +
+

Jev

+
+

+ + Ready + ••••7f3a +

+
+ + +
+
+
+
+

Site permissions

+
+
+ mybank.com +
+ + + +
+
+
+ Default for other sites +
+
+
+ +
+ +
+ +
+
+ +
Advanced
+
+ + diff --git a/packages/extension/store-assets/screens/render.sh b/packages/extension/store-assets/screens/render.sh new file mode 100755 index 0000000..f18e996 --- /dev/null +++ b/packages/extension/store-assets/screens/render.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Render the store graphics to ../*.png at their exact sizes, as 24-bit PNGs +# with no alpha (the Chrome Web Store rejects alpha): the five 1280×800 +# screenshots ([0-9]-*.html) and the two promo tiles (tile-*.html). Needs +# chrome-headless-shell (Playwright installs one: npx playwright install +# chromium-headless-shell) and python3 with Pillow. Full Chrome's --headless +# can hang on exit on macOS; the shell does not. +set -euo pipefail +cd "$(dirname "$0")" +CHROME="${CHROME:-$(ls -d "$HOME"/Library/Caches/ms-playwright/chromium_headless_shell-*/chrome-headless-shell-*/chrome-headless-shell 2>/dev/null | tail -1)}" +[ -x "$CHROME" ] || { echo "chrome-headless-shell not found; set CHROME=" >&2; exit 1; } +TMP="$(mktemp -d)" +trap 'rm -rf "$TMP"' EXIT + +# Pass files to render a subset: ./render.sh 2-popup.html tile-small.html +if [ $# -eq 0 ]; then set -- [0-9]-*.html tile-*.html; fi +for f in "$@"; do + case "$f" in + tile-small.html) out="small-tile-440x280.png" w=440 h=280 ;; + tile-marquee.html) out="marquee-1400x560.png" w=1400 h=560 ;; + [0-9]-*.html) out="screenshot-${f%%-*}-1280x800.png" w=1280 h=800 ;; + *) echo "unknown slide: $f" >&2; exit 1 ;; + esac + "$CHROME" --hide-scrollbars --force-device-scale-factor=1 --window-size="$w,$h" --virtual-time-budget=4000 \ + --screenshot="$TMP/out.png" "file://$PWD/$f" >/dev/null 2>&1 + python3 - "$TMP/out.png" "../$out" "$w" "$h" <<'PY' +import sys +from PIL import Image +im = Image.open(sys.argv[1]).convert("RGB") +assert im.size == (int(sys.argv[3]), int(sys.argv[4])), im.size +im.save(sys.argv[2], optimize=True) +PY + echo "$out" +done diff --git a/packages/extension/store-assets/screens/shared.css b/packages/extension/store-assets/screens/shared.css new file mode 100644 index 0000000..2ab807f --- /dev/null +++ b/packages/extension/store-assets/screens/shared.css @@ -0,0 +1,418 @@ +/* Chrome Web Store screenshots, 1280×800. Same language as reins.tech: the + words are mono and square, the drawings of real UI (browser, popup) are + sans and keep their corners. Render with ./render.sh. */ +@import url("https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400..700&family=Inter:wght@400..700&display=block"); + +:root { + --bg: #ffffff; + --ink: #18181b; + --ink-2: #3f3f46; + --muted: #71717a; + --faint: #a1a1aa; + --line: rgb(24 24 27 / 0.1); + --line-strong: rgb(24 24 27 / 0.18); + --fill: rgb(24 24 27 / 0.04); + --primary: #7c3aed; + --primary-ink: #6d28d9; + --primary-tint: rgb(124 58 237 / 0.08); + --term-bg: #16161a; + --term-ink: #e4e4e7; + --term-muted: #8b8b95; + --term-accent: #a78bfa; + --ok: #16a34a; + --err: #dc2626; + --mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace; + --sans: "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif; +} + +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + width: 1280px; + height: 800px; + overflow: hidden; + background: var(--bg); + color: var(--ink); + font-family: var(--mono); + -webkit-font-smoothing: antialiased; +} + +.slide { + position: relative; + width: 1280px; + height: 800px; + overflow: hidden; + padding: 56px 72px 0; + /* the faint grid the eye reads as paper, not decoration */ + background-image: + linear-gradient(var(--line) 1px, transparent 1px), + linear-gradient(90deg, var(--line) 1px, transparent 1px); + background-size: 32px 32px; + background-position: -1px -1px; +} + +.slide::before { + /* fade the grid out under the caption so the words sit on white */ + content: ""; + position: absolute; + inset: 0; + background: linear-gradient( + 180deg, + #fff 0%, + #fff 30%, + rgb(255 255 255 / 0.55) 60%, + rgb(255 255 255 / 0.2) 100% + ); + pointer-events: none; +} + +.slide > * { + position: relative; +} + +/* ---- caption --------------------------------------------------------- */ + +.meta { + display: flex; + align-items: center; + justify-content: space-between; + font-size: 15px; + color: var(--muted); + letter-spacing: 0.02em; +} + +.brand { + display: flex; + align-items: center; + gap: 10px; + color: var(--ink); + font-weight: 600; + font-size: 17px; +} + +.brand svg { + width: 26px; + height: 26px; +} + +.headline { + margin: 34px 0 0; + font-size: 40px; + line-height: 1.15; + font-weight: 650; + letter-spacing: 0.01em; + text-transform: uppercase; + text-wrap: balance; +} + +.headline .hash { + color: var(--primary); + margin-right: 14px; +} + +.sub { + margin: 16px 0 0; + max-width: 64ch; + font-size: 19px; + line-height: 1.5; + color: var(--ink-2); + border-left: 3px solid var(--primary); + padding-left: 16px; +} + +.sub code { + color: var(--primary-ink); + font-weight: 600; +} + +/* ---- terminal ---------------------------------------------------------- */ + +.term { + background: var(--term-bg); + color: var(--term-ink); + border-radius: 12px; + box-shadow: + 0 0 0 1px rgb(0 0 0 / 0.6), + 0 30px 60px -20px rgb(24 24 27 / 0.45), + 0 12px 24px -12px rgb(24 24 27 / 0.3); + font-family: var(--mono); + overflow: hidden; +} + +.term__bar { + display: flex; + align-items: center; + gap: 8px; + padding: 12px 16px; + border-bottom: 1px solid rgb(255 255 255 / 0.08); + font-size: 12px; + color: var(--term-muted); +} + +.term__bar i { + width: 11px; + height: 11px; + border-radius: 50%; + background: #3f3f46; +} + +.term__bar span { + margin-left: 10px; +} + +.term pre { + margin: 0; + padding: 18px 22px 22px; + font-family: inherit; + font-size: 16px; + line-height: 1.75; + white-space: pre; +} + +.term .p { + color: var(--term-accent); +} +.term .c { + color: #fff; + font-weight: 500; +} +.term .o { + color: var(--term-muted); +} +.term .ok { + color: #4ade80; +} +.term .er { + color: #f87171; +} +.term .hl { + color: #fde68a; +} +.term .caret { + display: inline-block; + width: 9px; + height: 18px; + vertical-align: -3px; + background: var(--term-accent); +} + +/* ---- browser window ------------------------------------------------------ */ + +.browser { + font-family: var(--sans); + background: #fff; + border-radius: 12px; + box-shadow: + 0 0 0 1px var(--line-strong), + 0 40px 80px -30px rgb(24 24 27 / 0.35), + 0 16px 32px -16px rgb(24 24 27 / 0.2); + overflow: hidden; +} + +.tabs { + display: flex; + align-items: flex-end; + gap: 2px; + height: 42px; + padding: 0 12px; + background: #dfe1e5; +} + +.tabs .lights { + display: flex; + gap: 8px; + align-self: center; + margin: 0 14px 0 4px; +} + +.tabs .lights i { + width: 12px; + height: 12px; + border-radius: 50%; +} +.tabs .lights i:nth-child(1) { + background: #ff5f57; +} +.tabs .lights i:nth-child(2) { + background: #febc2e; +} +.tabs .lights i:nth-child(3) { + background: #28c840; +} + +.tab { + display: flex; + align-items: center; + gap: 8px; + height: 34px; + width: 200px; + padding: 0 12px; + font-size: 12.5px; + color: #3c4043; + border-radius: 8px 8px 0 0; + white-space: nowrap; + overflow: hidden; +} + +.tab--active { + background: #fff; +} + +.tab .fav { + width: 14px; + height: 14px; + border-radius: 3px; + flex: none; +} + +.group-chip { + align-self: center; + margin: 0 2px 0 6px; + padding: 3px 9px; + border-radius: 6px; + font-size: 12px; + font-weight: 600; + color: #fff; + background: #8b5cf6; +} + +.group-line { + box-shadow: inset 0 -2px 0 #8b5cf6; +} + +.toolbar { + display: flex; + align-items: center; + gap: 12px; + height: 44px; + padding: 0 14px; + border-bottom: 1px solid #e5e7eb; +} + +.toolbar .nav { + display: flex; + gap: 14px; + color: #5f6368; + font-size: 15px; +} + +.omnibox { + flex: 1; + display: flex; + align-items: center; + gap: 8px; + height: 30px; + padding: 0 14px; + border-radius: 15px; + background: #f1f3f4; + font-size: 13.5px; + color: #202124; +} + +.omnibox .lock { + color: #5f6368; + font-size: 12px; +} + +.omnibox .host { + color: #202124; +} +.omnibox .path { + color: #5f6368; +} + +.ext { + display: grid; + place-items: center; + width: 28px; + height: 28px; + border-radius: 50%; +} + +.ext svg { + width: 20px; + height: 20px; +} + +.ext--on { + background: #ede9fe; +} + +.ext .badge { + position: absolute; +} + +/* Chrome's own infobar while an extension is attached with chrome.debugger */ +.debugbar { + display: flex; + align-items: center; + gap: 10px; + height: 38px; + padding: 0 16px; + font-size: 13px; + color: #202124; + background: #fff; + border-bottom: 1px solid #e5e7eb; +} + +.debugbar .icon { + width: 16px; + height: 16px; + border-radius: 50%; + border: 2px solid #1a73e8; + position: relative; +} + +.debugbar .icon::after { + content: ""; + position: absolute; + inset: 3px; + border-radius: 50%; + background: #1a73e8; +} + +.debugbar .cancel { + margin-left: auto; + padding: 5px 14px; + border: 1px solid #dadce0; + border-radius: 6px; + color: #1a73e8; + font-weight: 500; +} + +/* ref chips: what `reins snapshot` calls each element */ +.ref { + position: absolute; + z-index: 3; + padding: 3px 6px; + font-family: var(--mono); + font-size: 11.5px; + font-weight: 600; + line-height: 1; + color: #fff; + background: var(--primary); + border-radius: 3px; + box-shadow: 0 2px 6px rgb(124 58 237 / 0.35); +} + +.ref--dark { + background: var(--ink); + box-shadow: 0 2px 6px rgb(0 0 0 / 0.3); +} + +.outlined { + outline: 2px solid var(--primary); + outline-offset: 2px; +} + +.cursor { + position: absolute; + z-index: 4; + width: 22px; + height: 22px; + filter: drop-shadow(0 2px 3px rgb(0 0 0 / 0.3)); +} diff --git a/packages/extension/store-assets/screens/tile-marquee.html b/packages/extension/store-assets/screens/tile-marquee.html new file mode 100644 index 0000000..d71d36b --- /dev/null +++ b/packages/extension/store-assets/screens/tile-marquee.html @@ -0,0 +1,39 @@ + + + + + + + + + +
+
+ reins +

#Drive the browser you're signed in to

+

$ npm i -g @karnstack/reins

+
+
+
claude — ~/acme
+
$ reins snapshot
+e7: button "Export CSV"
+e9: textbox "Search invoices"
+$ reins click --ref e7
+ok
+$ reins do 'open the latest invoice'
+done in 2.9s · 2 steps · 3 jev calls · 9k tokens
+$ 
+
+
+ + diff --git a/packages/extension/store-assets/screens/tile-small.html b/packages/extension/store-assets/screens/tile-small.html new file mode 100644 index 0000000..9683a29 --- /dev/null +++ b/packages/extension/store-assets/screens/tile-small.html @@ -0,0 +1,23 @@ + + + + + + + + + +
+ reins +

Drive your real browser from your coding agent.

+

$ reins click --ref e7

+
+ + diff --git a/packages/extension/store-assets/screens/tile.css b/packages/extension/store-assets/screens/tile.css new file mode 100644 index 0000000..c7b7cd2 --- /dev/null +++ b/packages/extension/store-assets/screens/tile.css @@ -0,0 +1,46 @@ +/* Promo tiles. The store shows them on white, often small, so unlike the + screenshots they sit on the terminal's dark ground. */ +html, +body { + background: var(--term-bg); +} + +.tile { + position: relative; + overflow: hidden; + color: #fff; + background-color: var(--term-bg); + background-image: + radial-gradient(120% 90% at 100% 100%, rgb(124 58 237 / 0.45), transparent 60%), + linear-gradient(rgb(255 255 255 / 0.05) 1px, transparent 1px), + linear-gradient(90deg, rgb(255 255 255 / 0.05) 1px, transparent 1px); + background-size: + auto, + 24px 24px, + 24px 24px; +} + +.tile > * { + position: relative; +} + +.tile .brand { + color: #fff; +} + +:where(.tile p) { + margin: 0; +} + +.tile em { + font-style: normal; + color: var(--term-accent); +} + +.tile .cmd { + color: var(--term-muted); +} + +.tile .p { + color: var(--term-accent); +} diff --git a/packages/extension/store-assets/screenshot-1-1280x800.png b/packages/extension/store-assets/screenshot-1-1280x800.png new file mode 100644 index 0000000..fc8349e Binary files /dev/null and b/packages/extension/store-assets/screenshot-1-1280x800.png differ diff --git a/packages/extension/store-assets/screenshot-1280x800.png b/packages/extension/store-assets/screenshot-1280x800.png deleted file mode 100644 index 5ade67a..0000000 Binary files a/packages/extension/store-assets/screenshot-1280x800.png and /dev/null differ diff --git a/packages/extension/store-assets/screenshot-2-1280x800.png b/packages/extension/store-assets/screenshot-2-1280x800.png new file mode 100644 index 0000000..14f9995 Binary files /dev/null and b/packages/extension/store-assets/screenshot-2-1280x800.png differ diff --git a/packages/extension/store-assets/screenshot-3-1280x800.png b/packages/extension/store-assets/screenshot-3-1280x800.png new file mode 100644 index 0000000..8ba4ec4 Binary files /dev/null and b/packages/extension/store-assets/screenshot-3-1280x800.png differ diff --git a/packages/extension/store-assets/screenshot-4-1280x800.png b/packages/extension/store-assets/screenshot-4-1280x800.png new file mode 100644 index 0000000..b3e5261 Binary files /dev/null and b/packages/extension/store-assets/screenshot-4-1280x800.png differ diff --git a/packages/extension/store-assets/screenshot-5-1280x800.png b/packages/extension/store-assets/screenshot-5-1280x800.png new file mode 100644 index 0000000..5857a26 Binary files /dev/null and b/packages/extension/store-assets/screenshot-5-1280x800.png differ diff --git a/packages/extension/store-assets/small-tile-440x280.png b/packages/extension/store-assets/small-tile-440x280.png index ca31d73..21e9b70 100644 Binary files a/packages/extension/store-assets/small-tile-440x280.png and b/packages/extension/store-assets/small-tile-440x280.png differ