From 65ebde5385d46263165f0cff459a370b120a6412 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Tue, 9 Jun 2026 08:35:59 -0700 Subject: [PATCH] chore: bump version and changelog (v1.59.1.0) Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ VERSION | 2 +- package.json | 2 +- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 967255d61..3deb9b1db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,72 @@ # Changelog +## [1.59.1.0] - 2026-06-09 + +## **`browse` is now the one Chromium on the box, for offline rendering too.** +## **`js`/`eval --out ` writes a render straight to disk, so skills stop bundling their own puppeteer.** + +You can now turn your own local HTML or JSON into a PNG (or any bytes) on disk +through the same headless `browse` Chromium you already run, with no second +browser install. `js "" --out out.png` and `eval script.js --out out.png` +write the evaluate result to a file instead of returning it. When the result is a +base64 data URL (the shape Excalidraw exports, og-image generators, and card +renderers hand back), `--out` decodes it to raw bytes for you; pass `--raw` to +write the literal string. Malformed base64 errors loudly instead of writing a +corrupt file, and missing parent directories are created. This closes the gap that +made local-render skills each `npm i puppeteer` and download a drifting second +Chromium. + +### The numbers that matter + +No synthetic benchmark — these are structural facts of the change, verifiable from +the diff and a one-line smoke (`browse load-html` → `screenshot --selector` / +`js --out`). + +| For a skill that rasterizes local HTML/JSON | Before | After | +|---|---|---| +| Chromium installs per box | 2+ (browse + each skill's own puppeteer) | 1 (shared `browse`) | +| Getting a PNG from a render function | `evaluate` → multi-MB data URL over the CLI channel → hand-decode base64 → write | `js --out` decodes and writes server-side; only a short status crosses the channel | +| Render-to-file primitive | none | `js`/`eval --out [--raw]` | + +The blessed offline path is documented in the browse skill: visual output goes +through `screenshot --selector` (the picture never crosses the CDP wire), and bytes +a function returns go through `js --out`. + +### What this means for you + +If you write skills that draw diagrams, cards, or og-images, point them at `browse` +and delete the bundled Chromium. One version to pin, one daemon to manage. `--out` +is treated as a write everywhere it matters: it needs the `write` scope, is blocked +over the pair-agent tunnel, and is gated in watch mode, so a remote agent can never +use it to write to your disk. + +### Itemized changes + +#### Added +- **`js` / `eval --out ` render-to-file** (`browse/src/read-commands.ts`). + Writes the evaluate result to disk and returns a short `... result written: + ( bytes)` status. A `data:;base64,...` result is decoded to raw bytes + (case-insensitive header parse, split on the first comma, base64-charset validated + before decode); `--raw` forces a literal write. Parent directories are created. +- **`--raw` flag** to bypass data-URL decoding and write the literal result string. +- **Offline render mode docs** in the browse skill: an explicit headless, no-proxy, + no-Xvfb path with a worked example showing visual (`screenshot --selector`) vs + bytes (`js --out`), a puppeteer→browse cheatsheet row, and a "don't bundle your + own Chromium" note (also in CONTRIBUTING.md). + +#### Changed +- **`--out` is a per-invocation WRITE capability** (`browse/src/server.ts`). + `js`/`eval` stay read commands, but an `--out` invocation requires the `write` + scope, is never dispatchable over the tunnel surface (`canDispatchOverTunnel` now + consults args), and counts as a mutation for watch-mode and tab-ownership gates. + +#### For contributors +- New tests: `parseOutArgs`/`hasOutArg` unit coverage (`--out`/`--out=`, `--raw`, + repeats, missing value, ordering), `--out` render-to-file integration (large + string, data-URL→PNG, `--raw`, malformed-base64, outside-safe-dir, mkdir, eval + parity, byte-for-byte null/undefined), and tunnel-gate guards proving `--out` + is never tunnel-dispatchable. + ## [1.57.7.0] - 2026-06-08 ## **Every plan review now ends by telling you, in one line, whether anything is still unresolved.** diff --git a/VERSION b/VERSION index bb68a65d9..504ad96af 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.57.7.0 +1.59.1.0 diff --git a/package.json b/package.json index 229d7034c..0dd83531c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.57.7.0", + "version": "1.59.1.0", "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.", "license": "MIT", "type": "module",