Skip to content

Releases: 1m93/EngineShelf

1.1.6

Choose a tag to compare

@linhnt-1067 linhnt-1067 released this 07 Sep 08:13
d3d25f1

Fixed

  • The 1.1.5 downloads were missing lib/engines.sh and lib/engines.ps1.
    Every entry point sources that file — the CLI, the container launcher and both
    managers — so a downloaded 1.1.5 could not start; features.tsv was left out
    too, which turns every row's changelog into N/A. tools/release.sh copies
    both now. The repo checkout was never affected, which is why it shipped.
  • A scheduled Chromium catalog refresh deleted the other three shelves.
    tools/refresh-catalog.py builds its output from scratch and truncates
    catalog.tsv, and it did not read back the S rows it does not own — so on the
    run of 2026-08-31 all 288 shelf rows went. tools/sync-landing.py then
    republished the landing page from the emptied catalog: no Firefox, Edge or
    WebKit timeline at all and a hero counting zero versions. It had printed a
    warning about exactly that and written anyway; a warning is not a guard when
    the caller is a cron job. The refresh now carries foreign rows across verbatim,
    and the sync refuses to publish an empty shelf.
  • The Windows manager could not start on a machine without Docker. A bare
    docker call throws CommandNotFoundException, which 2>$null does not catch,
    and this one ran at startup outside any request handler.
  • tools/obfuscate.sh orphaned block comments. Stripping #-leading lines
    took the opening <# of a <# … #> block and left the closer behind, so a
    release-built .ps1 could fail to parse. Blocks are dropped whole now.
  • Docker actions for a selector no image understands are refused up front rather
    than failing with the reason buried in a job log.

Upgrading

  • Rebuild WebKit containers. The base image is chosen per revision now, and an
    image built by 1.1.5 may be the wrong pair — the one that builds and then dies
    at exec. ./engineshelf-docker.sh rebuild webkit:16.4, or Rebuild image in
    the row's menu.
  • Windows, Docker inside WSL: nothing to do, but the dependency doctor will
    now offer to finish an incomplete WSL 2 install instead of hanging.
  • Everything else needs nothing: extract over the old copy and start it. Browsers
    and profiles are untouched.

Artifacts: EngineShelf-1.1.6-macOS.zip, EngineShelf-1.1.6-Windows.zip,
EngineShelf-1.1.6-Linux.tar.gz. Verify with SHA256SUMS.txt.

1.1.5

Choose a tag to compare

@1m93 1m93 released this 27 Aug 19:58
32eeddc

EngineShelf 1.1.5

The project was Chromium-only and called ChromiumStack. It now holds four
engines — Chromium, Firefox, Edge and WebKit — and has the name to match. 288
versions on the shelf instead of 21, and none of them typed in by hand.

Renamed: ChromiumStack is now EngineShelf

The repository moved to github.com/1m93/EngineShelf, so download links from
older pages will not resolve.

Was Is
ChromiumStack-<ver>-macOS.zip EngineShelf-<ver>-macOS.zip
ChromiumStack.app / ChromiumStack.bat EngineShelf.app / EngineShelf.bat
chromium-stack.sh / .ps1 engineshelf.sh / .ps1
chromium-stack-docker.sh / .ps1 engineshelf-docker.sh / .ps1
~/.chromium-stack/ ~/.engineshelf/
chromium-stack:<rev> (Docker) engineshelf:<key>

Nothing has to be re-downloaded. On first run, ~/.chromium-stack is moved
to ~/.engineshelf — builds, profiles and logs intact. ~/.browsers-emu, the
name before that, is adopted the same way. Chromium builds keep the bare revision
as their on-disk name, so nothing already installed is stranded.

If you point the home somewhere else with an environment variable, rename it to
ENGINESHELF_HOME
. BROWSERS_EMU_HOME is still read everywhere;
CHROMIUM_STACK_HOME is read by the command line only, so leaving that one set
would have the manager and the container launcher looking in ~/.engineshelf
while the CLI works out of your chosen directory.

Docker is the one exception — see Upgrading.

Three more engines

A selector now names an engine and a version. A bare number still means Chromium,
which is every selector this tool used to accept:

./engineshelf.sh run 120          # Chromium, as before
./engineshelf.sh run firefox:115
./engineshelf.sh run edge:151
./engineshelf.sh run webkit:18.2
Engine Reaches back to Builds come from The catch
Chromium 2017 · milestone 60 the Chromium snapshot archive nothing is pruned — any revision works, not just catalogued ones
Firefox 2017 · Firefox 51 ftp.mozilla.org, every release ever shipped old builds trust only the roots they shipped with, so the OS trust store is switched on for them
Edge 2021 in a container · about six months natively on macOS the Linux package pool, and Microsoft's enterprise feed mac downloads carry a per-file GUID that cannot be constructed, so natively only what the feed still lists is reachable. Windows gets no native Edge at all — the container is the only route
WebKit 2021 Playwright's build CDN builds are deleted over time and older OS releases pin different revisions, so a version can exist for Linux with no macOS archive ever published

Native engines per host: macOS all four, Linux all four, Windows
Chromium, Firefox and WebKit.

Two things worth naming:

  • Firefox gets a prepared profile. security.enterprise_roots.enabled is
    turned on, because a 2019 Firefox has never heard of the certificate
    authorities issued since it was built and rejects most of today's HTTPS
    without it. The updater and telemetry are off — a pinned build that updates
    itself is not a pinned build. Chromium's switches are not passed to it: an
    unknown -flag opens a dialog in Firefox rather than being ignored.
  • WebKit is listed as WebKit, never Safari. What opens is a MiniBrowser
    shell around the engine — no Safari interface, no Intelligent Tracking
    Prevention, no Safari media stack. It will catch a CSS property Safari has not
    shipped; it will not reproduce a seven-day cookie cap or an HLS stream.

Everything an engine differs in — display name, host platforms, on-disk name,
binary path, extraction, launch environment, launch flags — is answered in
lib/engines.sh and lib/engines.ps1, one function per question. Adding a
fifth engine touches those two files and the catalog, not the launcher.

The shelf builds itself

The old tools/refresh-catalog.py carried a hand-written MILESTONES list, so
the shelf only grew when somebody edited a Python file. Firefox alone has shipped
158 majors; that does not scale to four vendors.

tools/discover.py reads each vendor's own live index instead — chromiumdash,
product-details.mozilla.org with ftp.mozilla.org, the Microsoft Edge package
pool with the enterprise feed, and Playwright's CDN cross-checked against
playwright-core's browsers.json. Nothing in it names a version.

1.0.4 1.1.5
Chromium 21 curated milestones 92 releases, 60 → 152
Firefox 104 releases, 51 → 154
Edge 39 releases, 95 → 151
WebKit 53 builds, r1446 → 26.5

Each engine degrades on its own: one vendor being unreachable costs that column,
not the run, and an engine that returns nothing keeps the rows it already had
rather than emptying its tab as though it had been discontinued.

A changelog on every row

The shelf's notes used to be twenty-odd hand-written lines on curated Chromium
milestones — "aspect-ratio and :is() (88)" — and nothing at all for anything
else. Nobody was going to hand-write 288 of those, and no vendor publishes one a
tool can read.

tools/features.py inverts MDN's browser-compat-data by version instead, which
answers exactly the question somebody browsing a shelf is asking: what can I
test in this one that I could not test in the one before.
It writes
features.tsv260 of the 288 rows now carry a real changelog, ordered by
how notable each entry is, with a count for what a row has no space for.

That also makes the search box a feature index. Type aspect-ratio and you get
Chromium 88 and Firefox 89. The box takes an engine, a version, a revision, a
release date or a feature name.

The engine-comparison grid is gone. Comparing across engines is what search
does now, and the grid was two hundred lines of CSS answering it worse.

The manager

  • A splash screen while the server comes up, naming the step it is on — a
    slow start says which part is slow rather than sitting on one word.
  • An engine filter in the sidebar. Four engines share one shelf and most of
    the time you want one of them.
  • Sticky era headings2017 – 2019, 2020 – 2021, 2022 – 2023,
    2024 – today — with all four engines interleaved by release date. The
    heading stays on screen for as long as its rows do, the way a phone gallery
    keeps the month in view, so the per-era caption is gone: it read once.
  • Progress on the row, not in one bar at the top. Each row shows its own
    phase and percentage. A native launch and a Docker build can both be going on
    the same row, and both are now visible — the single global bar could only ever
    show whichever one it reached first.
  • Cancel on installs, launches and Docker builds, from the row or the log
    panel. The half-fetched archive and the part-unpacked directory go with it.
  • One log per job. The panel has a tab per job and keeps finished ones, so a
    log is still reachable after the next job starts; one button hides every
    finished tab (nothing is deleted — writing to that log brings its tab back),
    and the panel's top edge drags to resize.
  • Open the native window again. A browser you have lost behind other windows
    has no handle the page can reach, so the server raises it.
  • One manager at a time. Opening the app while it is running used to start a
    second server on the next port; the copy of Chrome already running took the new
    window, so the process the new manager was watching exited at once, it read
    that as "window closed", and it quit a second later — taking the first
    manager's containers down with it
    , and leaving a window pointing at a server
    that was gone. A launch now asks first, and reopens the existing window. On
    macOS, ⌘N opens a second window onto the same shelf.
  • New endpoints: /api/alive, /api/features, /api/logs, /api/log/<id>,
    /api/raise.
  • Removed: the Rosetta only filter (each row still says what it needs) and
    the add by revision dialog — raw revisions are a command-line thing
    (./engineshelf.sh run 638880), and such builds still group under
    Added by revision.

macOS: the window belongs to the app

EngineShelf.app is a real Cocoa app with a WKWebView in it, replacing the
tiny launcher that shelled out to Chrome in --app mode.

  • The Dock icon is EngineShelf's, and pressing it brings the manager back — from
    Stage Manager, from a hidden desktop. Before, the Dock icon belonged to Chrome,
    which answered a click by finding no window of its own and opening an ordinary
    New Tab window on google.com. A window parked in Stage Manager could not be got
    back at all.
  • No second browser profile on disk for the manager's own window.
  • CFBundleExecutable is a compiled binary now, which it has to be: a shell
    script works as one until the project sits under ~/Documents, ~/Desktop or
    ~/Downloads, where macOS attributes the file access to /bin/bash, denies it
    outright and never asks. With a binary, macOS asks once and remembers.
  • The bundle still works both ways — self-contained release, or the repo checkout
    with the scripts beside it.

Docker: four images

Dockerfile.firefox, Dockerfile.edge and Dockerfile.webkit join the Chromium
one, and engineshelf-docker.sh takes the same engine selectors as the launcher:

./engineshelf-docker.sh start edge:95        # no host can do this natively
./engineshelf-docker.sh start webkit:16.4    # no macOS archive was ever published
  • Edge is not a convenience here. The enterprise feed holds about six months,
    so on macOS and Windows the native launcher genuinely cannot reach Edge 95 or
    114. The Linux apt pool ha...
Read more

1.0.4

Choose a tag to compare

@linhnt-1067 linhnt-1067 released this 26 Aug 10:44

Docker stops being the second-class way to run a version, and the manager starts
behaving like an application: closing its window closes everything it started.

The Docker edition, visible in the manager

A version running in a container used to leave no trace on the shelf. The row
said "not installed" over a gigabyte of built image, and showed nothing at all
over a browser that was open — because the job that starts a container exits as
soon as the desktop answers, so there was no job left to look at.

The cause was a mismatch worth naming: a container always runs the Linux
x86_64
build, and the shelf was comparing its revision against the one this
host installs natively. For Chromium 60 that is 474900 against 474901, so
"Stop Docker container" never once appeared.

Now, per row:

  • the running dot and the Running filter count containers, not just native windows;
  • a green Docker marker shows the image size, or Docker · running when the
    container is up — and then it is a link back to the desktop tab, which was easy
    to close and impossible to find again;
  • the primary button is Stop while the container runs, and Launch when the
    image is built but idle: one click, no download;
  • the row menu offers Open the desktop, Stop the container, Launch
    natively as well
    , and Delete Docker image, with the size on the label —
    reclaiming that gigabyte previously meant raw docker commands;
  • the sidebar Disk read-out has a Docker line, and the header total includes
    it. On a machine with two images built, the old gauge was under-reporting by
    more than 2 GB.

Docker actions are only offered for milestones that actually have a Linux build
to put in a container. Before, the manager offered it for every row and let the
launcher fail with the reason buried in a job log.

Copy and paste in the container's desktop

noVNC ships a clipboard side panel and nothing else: the canvas swallows every
keystroke, so text copied anywhere else on the machine could only get in by being
pasted into that panel by hand.

Both directions work now. Your usual shortcut pastes into the container, and
anything copied inside it lands on your own clipboard. On a Mac that means
Cmd-C, Cmd-V and Cmd-X — which the Linux desktop in there would otherwise
never see, since noVNC forwards Cmd as Super and no application answers Super-V.

The manager closes like an application

It used to be a tab you closed and a server you forgot about, still holding a
port and still parenting every browser it had launched.

  • The manager opens in a window of its own — a Chromium-family browser in
    --app mode with its own profile, which is what makes closing it unambiguous
    and keeps the manager out of your browsing session. Without such a browser it
    falls back to a tab.
  • Closing the window quits everything: the server stops, the browsers it
    launched close, and the containers it started come down. Ctrl-C in a terminal
    does the same.
  • If any of that is still running, the browser asks you to confirm first, so a
    stray click on the X cannot take a download with it. Idle, the window closes
    without a word.
  • A download interrupted by the shutdown is cleared up rather than left as an
    80 MB orphan that can never be resumed. Only for versions this manager was
    working on — a second manager against the same directory keeps its own.
  • Suspending the machine is not a closed window. Shutting a laptop lid used to be
    indistinguishable from closing the manager, given a heartbeat that had simply
    stopped arriving.

New flags on gui.sh / gui.ps1: --tab for a tab in your default browser,
--keep-alive to leave the server running whatever the window does, and
--no-open (which implies --keep-alive) for a bare server.

Fixed

  • Two versions in Docker at once. Both starts saw port 6080 free, and the one
    that lost the race reported "Could not start the container". A refused binding
    now moves up a port and tries again.
  • A version that could never start again. stop removed its container
    outright, so the browser inside never got to release the lock in its profile
    volume. The next start then failed with "the profile appears to be in use by
    another Chromium process on another computer"
    — permanently, for that version,
    after one hard stop or one crash. Containers are now stopped with SIGTERM first,
    the entrypoint passes it on to Chromium, and a lock left behind by a container
    that is already gone is cleared at startup.
  • Chromium 60 in Docker died on startup, exit 127: the oldest milestones link
    against libgconf-2.so.4, which Debian dropped after buster. The image now
    fetches it from the Debian archive — so the milestones Rosetta is least
    reliable with are the ones the container can now actually run.
  • The container's log named Chromium 74 whatever revision it was actually
    running.

Changed

  • The container's desktop is published on 127.0.0.1 only. It has no password
    and a real browser attached to it, and a plain -p put it in front of everyone
    on the network.
  • ~/.chromium-stack/manager-window/ appears: the browser profile behind the
    manager's own window, a few tens of MB of browser plumbing. Safe to delete when
    the manager is closed.

Upgrading

Rebuild any Docker images you already have. The clipboard bridge and the
libgconf fix are baked into the image, so an image built by an earlier version
has neither:

./chromium-stack-docker.sh rebuild 74

Everything else is scripts and the page — extracting over the old copy is enough.

1.0.3

Choose a tag to compare

@linhnt-1067 linhnt-1067 released this 26 Aug 09:10
feat: update landing page

1.0.2

Choose a tag to compare

@linhnt-1067 linhnt-1067 released this 26 Aug 02:39
feat: update release

1.0.1

Choose a tag to compare

@1m93 1m93 released this 25 Aug 07:19
fix: macos build support